summaryrefslogtreecommitdiff
path: root/docs/content/guides
diff options
context:
space:
mode:
Diffstat (limited to 'docs/content/guides')
-rw-r--r--docs/content/guides/auth/github.md35
-rw-r--r--docs/content/guides/auth/gitlab-self-hosted.md30
-rw-r--r--docs/content/guides/auth/keycloak.md49
-rw-r--r--docs/content/guides/auth/ldap-ad.md38
-rw-r--r--docs/content/guides/auth/mattermost-self-hosted.md56
-rw-r--r--docs/content/guides/auth/nextcloud.md52
-rw-r--r--docs/content/guides/auth/oauth.md12
-rw-r--r--docs/content/guides/auth/saml-keycloak.md113
-rw-r--r--docs/content/guides/auth/saml-onelogin.md55
-rw-r--r--docs/content/guides/auth/saml.md97
-rw-r--r--docs/content/guides/auth/twitter.md42
-rw-r--r--docs/content/guides/migrate-etherpad.md128
-rw-r--r--docs/content/guides/migrations-and-breaking-changes.md55
-rw-r--r--docs/content/guides/minio-image-upload.md94
-rw-r--r--docs/content/guides/providing-terms.md25
-rw-r--r--docs/content/guides/s3-image-upload.md77
16 files changed, 958 insertions, 0 deletions
diff --git a/docs/content/guides/auth/github.md b/docs/content/guides/auth/github.md
new file mode 100644
index 00000000..f540a530
--- /dev/null
+++ b/docs/content/guides/auth/github.md
@@ -0,0 +1,35 @@
+# Authentication guide - GitHub
+
+1. Sign-in or sign-up for a GitHub account
+
+2. Navigate to developer settings in your GitHub account [here](https://github.com/settings/developers) and select the "OAuth Apps" tab
+
+3. Click on the **New OAuth App** button, to create a new OAuth App:
+ ![create-oauth-app](../../images/auth/create-oauth-app.png)
+
+4. Fill out the new OAuth application registration form, and click **Register Application**
+ ![register-oauth-application-form](../../images/auth/register-oauth-application-form.png)
+
+ **Note:** *The callback URL is <your-hedgedoc-url>/auth/github/callback*
+
+5. After successfully registering the application, you'll receive the Client ID and Client Secret for the application
+ ![application-page](../../images/auth/application-page.png)
+
+6. Add the Client ID and Client Secret to your config.json file or pass them as environment variables
+ - `config.json`:
+ ```js
+ {
+ "production": {
+ "github": {
+ "clientID": "3747d30eaccXXXXXXXXX",
+ "clientSecret": "2a8e682948eee0c580XXXXXXXXXXXXXXXXXXXXXX"
+ }
+ }
+ }
+ ```
+
+ - environment variables:
+ ```sh
+ CMD_GITHUB_CLIENTID=3747d30eaccXXXXXXXXX
+ CMD_GITHUB_CLIENTSECRET=2a8e682948eee0c580XXXXXXXXXXXXXXXXXXXXXX
+ ````
diff --git a/docs/content/guides/auth/gitlab-self-hosted.md b/docs/content/guides/auth/gitlab-self-hosted.md
new file mode 100644
index 00000000..fc655ac5
--- /dev/null
+++ b/docs/content/guides/auth/gitlab-self-hosted.md
@@ -0,0 +1,30 @@
+# GitLab (self-hosted)
+
+*Note:* This guide was written before the renaming. Just replace `HackMD` with `HedgeDoc` in your mind :smile: thanks!
+
+1. Sign in to your GitLab
+2. Navigate to the application management page at `https://your.gitlab.domain/admin/applications` (admin permissions required)
+3. Click **New application** to create a new application and fill out the registration form:
+
+![New GitLab application](../../images/auth/gitlab-new-application.png)
+
+4. Click **Submit**
+5. In the list of applications select **HackMD**. Leave that site open to copy the application ID and secret in the next step.
+
+![Application: HackMD](../../images/auth/gitlab-application-details.png)
+
+6. In the `docker-compose.yml` add the following environment variables to `app:` `environment:`
+
+```Dockerfile
+- CMD_DOMAIN=your.hedgedoc.domain
+- CMD_URL_ADDPORT=true
+- CMD_PROTOCOL_USESSL=true
+- CMD_GITLAB_BASEURL=https://your.gitlab.domain
+- CMD_GITLAB_CLIENTID=23462a34example99XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+- CMD_GITLAB_CLIENTSECRET=5532e9dexamplXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+```
+
+7. Run `docker-compose up -d` to apply your settings.
+8. Sign in to your HedgeDoc using your GitLab ID:
+
+![Sign in via GitLab](../../images/auth/gitlab-sign-in.png)
diff --git a/docs/content/guides/auth/keycloak.md b/docs/content/guides/auth/keycloak.md
new file mode 100644
index 00000000..82f6d321
--- /dev/null
+++ b/docs/content/guides/auth/keycloak.md
@@ -0,0 +1,49 @@
+# OAuth with Keycloak/Red Hat SSO (self-hosted)
+
+## Prerequisites
+
+This guide assumes you have run and configured Keycloak. If you'd like to meet this prerequisite quickly, it can be achieved by running a `jboss/keycloak` container and attaching it to your network. Set the environment variables KEYCLOAK_USER and `KEYCLOAK_PASSWORD`, and expose port 8080.
+
+Where HTTPS is specified throughout, use HTTP instead. You may also have to specify the exposed port, 8080.
+
+## Steps
+
+1. Sign in to the administration portal for your Keycloak instance at <https://keycloak.example.com/auth/admin/master/console>
+
+You may note that a separate realm is specified throughout this tutorial. It is best practice not to use the master realm, as it normally contains the realm-management client that federates access using the policies and permissions you can create.
+
+2. Navigate to the client management page at `https://keycloak.example.com/auth/admin/master/console/#/realms/your-realm/clients` (admin permissions required)
+3. Click **Create** to create a new client and fill out the registration form. You should set the Root URL to the fully qualified public URL of your HedgeDoc instance.
+4. Click **Save**
+5. Set the **Access Type** of the client to `confidential`. This will make your client require a client secret upon authentication.
+
+---
+
+### Additional steps to circumvent generic OAuth2 issue
+
+1. Select Client Scopes from the sidebar, and begin to create a new client scope using the Create button.
+2. Ensure that the **Name** field is set to `id`.
+3. Create a new mapper under the Mappers tab. This should reference the User Property `id`. `Claim JSON Type` should be String and all switches below should be enabled. Save the mapper.
+4. Go to the client you set up in the previous steps using the Clients page, then choose the Client Scopes tab. Apply the scope you've created. This should mitigate errors as seen in [hedgedoc/hedgedoc#56](https://github.com/hedgedoc/hedgedoc/issues/56), as the `/userinfo` endpoint should now bring back the user's ID under the `id` key as well as `sub`.
+
+---
+
+5. In the `docker-compose.yml` add the following environment variables to `app:` `environment:`
+
+```Dockerfile
+CMD_OAUTH2_USER_PROFILE_URL=https://keycloak.example.com/auth/realms/your-realm/protocol/openid-connect/userinfo
+CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR=preferred_username
+CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR=name
+CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR=email
+CMD_OAUTH2_TOKEN_URL=https://keycloak.example.com/auth/realms/your-realm/protocol/openid-connect/token
+CMD_OAUTH2_AUTHORIZATION_URL=https://keycloak.example.com/auth/realms/your-realm/protocol/openid-connect/auth
+CMD_OAUTH2_CLIENT_ID=<your client ID>
+CMD_OAUTH2_CLIENT_SECRET=<your client secret, which you can find under the Credentials tab for your client>
+CMD_OAUTH2_PROVIDERNAME=Keycloak
+CMD_DOMAIN=<hedgedoc.example.com>
+CMD_PROTOCOL_USESSL=true
+CMD_URL_ADDPORT=false
+```
+
+6. Run `docker-compose up -d` to apply your settings.
+7. Sign in to your HedgeDoc using your Keycloak ID
diff --git a/docs/content/guides/auth/ldap-ad.md b/docs/content/guides/auth/ldap-ad.md
new file mode 100644
index 00000000..b7d0284e
--- /dev/null
+++ b/docs/content/guides/auth/ldap-ad.md
@@ -0,0 +1,38 @@
+# AD LDAP auth
+
+To setup your HedgeDoc instance with Active Directory you need the following configs:
+
+```env
+CMD_LDAP_URL=ldap://internal.example.com
+CMD_LDAP_BINDDN=cn=binduser,cn=Users,dc=internal,dc=example,dc=com
+CMD_LDAP_BINDCREDENTIALS=<super secret password>
+CMD_LDAP_SEARCHBASE=dc=internal,dc=example,dc=com
+CMD_LDAP_SEARCHFILTER=(&(objectcategory=person)(objectclass=user)(|(sAMAccountName={{username}})(mail={{username}})))
+CMD_LDAP_USERIDFIELD=sAMAccountName
+CMD_LDAP_PROVIDERNAME=Example Inc AD
+```
+
+`CMD_LDAP_BINDDN` is either the `distinguishedName` or the `userPrincipalName`. *This can cause "username/password is invalid" when either this value or the password from `CMD_LDAP_BINDCREDENTIALS` are incorrect.*
+
+`CMD_LDAP_SEARCHFILTER` matches on all users and uses either the email address or the `sAMAccountName` (usually the login name you also use to login to Windows).
+
+*Only using `sAMAccountName` looks like this:* `(&(objectcategory=person)(objectclass=user)(sAMAccountName={{username}}))`
+
+`CMD_LDAP_USERIDFIELD` says we want to use `sAMAccountName` as unique identifier for the account itself.
+
+`CMD_LDAP_PROVIDERNAME` just the name written above the username and password field on the login page.
+
+Same in json:
+
+```json
+"ldap": {
+ "url": "ldap://internal.example.com",
+ "bindDn": "cn=binduser,cn=Users,dc=internal,dc=example,dc=com",
+ "bindCredentials": "<super secret password>",
+ "searchBase": "dc=internal,dc=example,dc=com",
+ "searchFilter": "(&(objectcategory=person)(objectclass=user)(|(sAMAccountName={{username}})(mail={{username}})))",
+ "useridField": "sAMAccountName",
+},
+```
+
+More details and example: <https://www.npmjs.com/package/passport-ldapauth>
diff --git a/docs/content/guides/auth/mattermost-self-hosted.md b/docs/content/guides/auth/mattermost-self-hosted.md
new file mode 100644
index 00000000..2ad2afd7
--- /dev/null
+++ b/docs/content/guides/auth/mattermost-self-hosted.md
@@ -0,0 +1,56 @@
+# Authentication guide - Mattermost (self-hosted)
+
+**Note:** *The Mattermost setup portion of this document is just a quick guide. See the [official documentation](https://docs.mattermost.com/developer/oauth-2-0-applications.html) for more details.*
+
+This guide uses the generic OAuth2 module for compatibility with Mattermost version 5.0 and above.
+
+1. Sign-in with an administrator account to your Mattermost instance
+
+2. Make sure **OAuth 2.0 Service Provider** is enabled in the Main Menu (menu button next to your username in the top left corner) --> System Console --> Custom Integrations menu, which you can find at `https://your.mattermost.domain/admin_console/integrations/custom`
+ ![mattermost-enable-oauth2](../../images/auth/mattermost-enable-oauth2.png)
+
+3. Navigate to the OAuth integration settings through Main Menu --> Integrations --> OAuth 2.0 Applications, at `https://your.mattermost.domain/yourteam/integrations/oauth2-apps`
+
+4. Click on the **Add OAuth 2.0 Application** button to add a new OAuth application
+ ![mattermost-oauth-app-add](../../images/auth/mattermost-oauth-app-add.png)
+
+5. Fill out the form and click **Save**
+ ![mattermost-oauth-app-form](../../images/auth/mattermost-oauth-app-form.png)
+
+*Note: The callback URL is \<your-hedgedoc-url\>/auth/oauth2/callback*
+
+6. After saving the application, you'll receive the Client ID and Client Secret
+ ![mattermost-oauth-app-done](../../images/auth/mattermost-oauth-app-done.png)
+
+7. Add the Client ID and Client Secret to your config.json file or pass them as environment variables
+ - `config.json`:
+ ```javascript
+ {
+ "production": {
+ "oauth2": {
+ "baseURL": "https://your.mattermost.domain",
+ "userProfileURL": "https://your.mattermost.domain/api/v4/users/me",
+ "userProfileUsernameAttr": "id",
+ "userProfileDisplayNameAttr": "username",
+ "userProfileEmailAttr": "email",
+ "tokenURL": "https://your.mattermost.domain/oauth/access_token",
+ "authorizationURL": "https://your.mattermost.domain/oauth/authorize",
+ "clientID": "ii4p1u3jz7dXXXXXXXXXXXXXXX",
+ "clientSecret": "mqzzx6fydbXXXXXXXXXXXXXXXX"
+ }
+ }
+ }
+ ```
+
+ - environment variables:
+ ```sh
+ CMD_OAUTH2_BASEURL=https://your.mattermost.domain
+ CMD_OAUTH2_USER_PROFILE_URL=https://your.mattermost.domain/api/v4/users/me
+ CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR=id
+ CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR=username
+ CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR=email
+ CMD_OAUTH2_TOKEN_URL=https://your.mattermost.domain/oauth/access_token
+ CMD_OAUTH2_AUTHORIZATION_URL=https://your.mattermost.domain/oauth/authorize
+ CMD_OAUTH2_CLIENT_ID=ii4p1u3jz7dXXXXXXXXXXXXXXX
+ CMD_OAUTH2_CLIENT_SECRET=mqzzx6fydbXXXXXXXXXXXXXXXX
+ ```
diff --git a/docs/content/guides/auth/nextcloud.md b/docs/content/guides/auth/nextcloud.md
new file mode 100644
index 00000000..e0eb28d1
--- /dev/null
+++ b/docs/content/guides/auth/nextcloud.md
@@ -0,0 +1,52 @@
+# Authentication guide - Nextcloud (self-hosted)
+
+*This has been constructed using the [Nextcloud OAuth2 Documentation](https://docs.nextcloud.com/server/14/admin_manual/configuration_server/oauth2.html?highlight=oauth2) combined with [this issue comment on the nextcloud bugtracker](https://github.com/nextcloud/server/issues/5694#issuecomment-314761326).*
+
+This guide uses the generic OAuth2 module for compatibility with Nextcloud 13 and above (this guide has been tested successfully with Nextcloud 14).
+
+1. Sign-in with an administrator account to your Nextcloud server
+
+2. Navigate to the OAuth integration settings: Profile Icon (top right) --> Settings
+ Then choose Security Settings from the *Administration* part of the list - Don't confuse this with Personal Security Settings, where you would change your personal password!
+ At the top there's OAuth 2.0-Clients.
+ ![Where to find OAuth2 in Nextcloud](../../images/auth/nextcloud-oauth2-1-settings.png)
+
+3. Add your HedgeDoc instance by giving it a *name* (perhaps HedgeDoc, but could be anything) and a *Redirection-URI*. The Redirection-URI will be `\<your-hedgedoc-url\>/auth/oauth2/callback`. Click <kbd>Add</kbd>.
+ ![Adding a client to Nextcloud](../../images/auth/nextcloud-oauth2-2-client-add.png)
+
+
+4. You'll now see a line containing a *client identifier* and a *Secret*.
+ ![Successfully added OAuth2-client](../../images/auth/nextcloud-oauth2-3-clientid-secret.png)
+
+5. That's it for Nextcloud, the rest is configured in your HedgeDoc `config.json` or via the `CMD_` environment variables!
+
+6. Add the Client ID and Client Secret to your `config.json` file or pass them as environment variables. Make sure you also replace `<your-nextcloud-domain>` with the right domain name.
+ - `config.json`:
+ ```javascript
+ {
+ "production": {
+ "oauth2": {
+ "clientID": "ii4p1u3jz7dXXXXXXXXXXXXXXX",
+ "clientSecret": "mqzzx6fydbXXXXXXXXXXXXXXXX",
+ "authorizationURL": "https://<your-nextcloud-domain>/apps/oauth2/authorize",
+ "tokenURL": "https://<your-nextcloud-domain>/apps/oauth2/api/v1/token",
+ "userProfileURL": "https://<your-nextcloud-domain>/ocs/v2.php/cloud/user?format=json",
+ "userProfileUsernameAttr": "ocs.data.id",
+ "userProfileDisplayNameAttr": "ocs.data.display-name",
+ "userProfileEmailAttr": "ocs.data.email"
+ }
+ }
+ }
+ ```
+
+ - environment variables:
+ ```sh
+ CMD_OAUTH2_CLIENT_ID=ii4p1u3jz7dXXXXXXXXXXXXXXX
+ CMD_OAUTH2_CLIENT_SECRET=mqzzx6fydbXXXXXXXXXXXXXXXX
+ CMD_OAUTH2_AUTHORIZATION_URL=https://<your-nextcloud-domain>/apps/oauth2/authorize
+ CMD_OAUTH2_TOKEN_URL=https://<your-nextcloud-domain>/apps/oauth2/api/v1/token
+ CMD_OAUTH2_USER_PROFILE_URL=https://<your-nextcloud-domain>/ocs/v2.php/cloud/user?format=json
+ CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR=ocs.data.id
+ CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR=ocs.data.display-name
+ CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR=ocs.data.email
+ ```
diff --git a/docs/content/guides/auth/oauth.md b/docs/content/guides/auth/oauth.md
new file mode 100644
index 00000000..de2ca20a
--- /dev/null
+++ b/docs/content/guides/auth/oauth.md
@@ -0,0 +1,12 @@
+# OAuth general information
+
+| service | callback URL (after the server URL) |
+| ---------- | ----------------------------------- |
+| facebook | `/auth/facebook/callback` |
+| twitter | `/auth/twitter/callback` |
+| github | `/auth/github/callback` |
+| gitlab | `/auth/gitlab/callback` |
+| mattermost | `/auth/mattermost/callback` |
+| dropbox | `/auth/dropbox/callback` |
+| google | `/auth/google/callback` |
+| saml | `/auth/saml/callback` |
diff --git a/docs/content/guides/auth/saml-keycloak.md b/docs/content/guides/auth/saml-keycloak.md
new file mode 100644
index 00000000..1bc3b363
--- /dev/null
+++ b/docs/content/guides/auth/saml-keycloak.md
@@ -0,0 +1,113 @@
+# How to setup HedgeDoc SAML with Keycloak
+## Configuring Keycloak
+### Get the public certificate
+1. Select the Realm you want to use for your HedgeDoc SAML
+2. Select "Realm Settings" in left sidebar
+3. Select the "Keys" tab
+4. Click the button "Certificate" at `RS256` algorithm
+![keycloak_idp_cert](../../images/auth/keycloak_idp_cert.png)
+5. Copy this key and save it to the file specified in `saml.idpCert` property of the HedgeDoc configuration or `CMD_SAML_IDPCERT` environment variable
+
+### Create a new client
+1. Select "Client" in left sidebar
+![keycloak_clients_overview](../../images/auth/keycloak_clients_overview.png)
+2. Click on the "Create" button
+3. Set a Client ID and specify this in `saml.issuer` property of the HedgeDoc configuration or `CMD_SAML_ISSUER` environment variable
+4. Select `SAML` as Client Protocol
+5. Set Client SAML Endpoint to `https://hedgedoc.example.com/auth/saml` (replace `https://hedgedoc.example.com` with the base URL of your HedgeDoc installation)
+![keycloak_add_client](../../images/auth/keycloak_add_client.png)
+6. Leave "Client Signature Required" enabled
+7. Set Root URL to `https://hedgedoc.example.com` (replace it here also with the base URL of your HedgeDoc installation)
+8. Set Valid Redirect URIs to `https://hedgedoc.example.com/auth/saml/callback` (you should also define all other domains of your HedgeDoc installtion with the suffix `/auth/saml/callback`)
+9. Set Base URL to `/`
+![keycloak_client_overview](../../images/auth/keycloak_client_overview.png)
+10. _(optional)_ You can set which Name ID Format should be used
+
+## Configure HedgeDoc
+### Config file
+You have to put the following block inside your `config.json`:
+```json
+"saml": {
+ "issuer": "hedgedoc", // Change to the "Client ID" specified in the Keycloak Client
+ "identifierFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
+ "idpSsoUrl": "https://keycloak.example.org/auth/realms/test/protocol/saml", // replace keycloak.example.org with the url of your keycloak server
+ "idpCert": "/path/to/the/cert.pem",
+ "clientCert": "/path/to/the/key.pem" // this one is optional, see below
+}
+```
+
+### Environment Variables
+- `CMD_SAML_IDPSSOURL`: `https://keycloak.example.org/auth/realms/test/protocol/saml` (replace keycloak.example.org with the url of your keycloak server)
+- `CMD_SAML_IDPCERT`: `/path/to/the/cert.pem`
+- *(optional, see below)* `CMD_SAML_CLIENTCERT`: `/path/to/the/key.pem`
+- `CMD_SAML_ISSUER`: `hedgedoc` (Change to the "Client ID" specified in the Keycloak Client)
+- `CMD_SAML_IDENTIFIERFORMAT`: `urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified`
+
+
+## Client certificate *(optional)*
+If you want keycloak to be able to verify HedgeDoc, you hava to create a client certificate. There are two options for this:
+
+### Create Private Keys for Signing
+1. Generate the private key and certificate with the following commands:
+```shell
+openssl genrsa -out priv.pem 2048
+openssl req -new -x509 -key priv.pem -out cert.pem
+```
+*execute the following steps in keycloak*
+
+2. Select "Client" in left sidebar
+3. Go to your HedgeDoc-Client
+4. Select the "SAML Keys" tab
+![keycloak_saml_import_cert](../../images/auth/keycloak_saml_import_cert.png)
+5. Click on "Import"
+6. Select `Certificate PEM` as "Archive Format"
+7. Now upload the generated cert.pem (in this case named `cert.pem`)
+![keycloak_saml_import_cert_details](../../images/auth/keycloak_saml_import_cert_details.png)
+8. Click on "Import"
+9. Move or copy this key (in this case named `key.pem`) and save it to the file specified in `saml.clientCert` property of the HedgeDoc configuration or in the enviroment-variable `CMD_SAML_CLIENTCERT`
+
+
+### Convert Private Certificate generated by KeyCloak
+Instead if generating you own certificate, you can also use the one generated by keycloak.
+
+1. Select "Client" in left sidebar
+2. Go to your HedgeDoc-Client
+3. Select the "SAML Keys" tab
+![keycloak_saml_export_cert](../../images/auth/keycloak_saml_export_cert.png)
+
+5. Now click on "Export"
+6. Here you can select the output format, choose `PKCS12`. You also have to set a password. Choose your own.
+![keycloak_saml_export_cert_details](../../images/auth/keycloak_saml_export_cert_details.png)
+6. Click on "Download" and save the file somewhere on you computer
+7. You now have to extract the private Key. You can do this with the following command. WHen asked, enter your password.
+```shell
+openssl pkcs12 -in keystore.p12 -out key.pem -nocerts -nodes
+```
+8. Move or copy this key (in this case named `key.pem`) and save it to the file specified in `saml.idpCert` property of the HedgeDoc configuration or in the enviroment-variable `CMD_SAML_CLIENTCERT`
+
+## Use Persistent Identifiers
+Instead of using the username as the owner-key in the HedgeDoc database, you can also use a persistent identifier. This allows to change the username, without them loosing access to their notes.
+
+1. Go to the HedgeDoc-Client in keycloak. Now enable the option "Force Name ID Format" and select "persistent" as the "Name ID Format".
+![keycloak_force_idformat](../../images/auth/keycloak_force_idformat.png)
+2. For HedgeDoc to be able to use the username and email configured in keycloak, you have to create the following SAML protocol mappers:
+ 2.1. Create a mapper with the type `User Property`. Set the Name, Property and SAML Attribute Name to `username`. Now you can specify a friendly name (for example `Username`)
+![keycloak_mapper_username](../../images/auth/keycloak_mapper_username.png)
+ 2.2 Create a mapper with the type `User Property`. Set the Name, Property and SAML Attribute Name to `email`. Now you can specify a friendly name (for example `E-Mail`)
+![keycloak_mapper_email](../../images/auth/keycloak_mapper_email.png)
+
+The configured mappers should look like this:
+![keycloak_mapper_overview](../../images/auth/keycloak_mapper_overview.png)
+
+3. You now have to add the following block to the saml-definition inside your `config.json`:
+```json
+"attribute": {
+ "username": "username"
+ "email": "email",
+}
+```
+It you configure HedgeDoc with enviroment variables, these are the ones you have to set:
+```bash
+CMD_SAML_ATTRIBUTE_USERNAME=username
+CMD_SAML_ATTRIBUTE_EMAIL=email
+```
diff --git a/docs/content/guides/auth/saml-onelogin.md b/docs/content/guides/auth/saml-onelogin.md
new file mode 100644
index 00000000..8b897c82
--- /dev/null
+++ b/docs/content/guides/auth/saml-onelogin.md
@@ -0,0 +1,55 @@
+# Authentication guide - SAML (OneLogin)
+
+**Note:** *This guide was written before the renaming. Just replace `HackMD` with `HedgeDoc` in your mind :smile: thanks!*
+
+1. Sign-in or sign-up for an OneLogin account. (available free trial for 2 weeks)
+
+2. Go to the administration page.
+
+3. Select the **APPS** menu and click on the **Add Apps**.
+ ![onelogin-add-app](../../images/auth/onelogin-add-app.png)
+
+4. Find "SAML Test Connector (SP)" for template of settings and select it.
+ ![onelogin-select-template](../../images/auth/onelogin-select-template.png)
+
+5. Edit display name and icons for OneLogin dashboard as you want, and click **SAVE**.
+ ![onelogin-edit-app-name](../../images/auth/onelogin-edit-app-name.png)
+
+6. After that other tabs will appear, click the **Configuration**, and fill out the below items, and click **SAVE**.
+ - RelayState: The base URL of your HedgeDoc, which is issuer. (last slash is not needed)
+
+ - ACS (Consumer) URL Validator: The callback URL of your HedgeDoc. (serverurl + /auth/saml/callback)
+
+ - ACS (Consumer) URL: same as above.
+
+ - Login URL: login URL(SAML requester) of your CopiMD. (serverurl + /auth/saml)
+ ![onelogin-edit-sp-metadata](../../images/auth/onelogin-edit-sp-metadata.png)
+
+7. The registration is completed. Next, click **SSO** and copy or download the items below.
+ - X.509 Certificate: Click **View Details** and **DOWNLOAD** or copy the content of certificate ....(A)
+
+ - SAML 2.0 Endpoint (HTTP): Copy the URL ....(B)
+ ![onelogin-copy-idp-metadata](../../images/auth/onelogin-copy-idp-metadata.png)
+
+8. In your HedgeDoc server, create IdP certificate file from (A)
+9. Add the IdP URL (B) and the Idp certificate file path to your config.json file or pass them as environment variables.
+ - `config.json`:
+ ```javascript
+ {
+ "production": {
+ "saml": {
+ "idpSsoUrl": "https://*******.onelogin.com/trust/saml2/http-post/sso/******",
+ "idpCert": "/path/to/idp_cert.pem"
+ }
+ }
+ }
+ ```
+
+ - environment variables
+ ```sh
+ CMD_SAML_IDPSSOURL=https://*******.onelogin.com/trust/saml2/http-post/sso/******
+ CMD_SAML_IDPCERT=/path/to/idp_cert.pem
+ ```
+
+10. Try sign-in with SAML from your HedgeDoc sign-in button or OneLogin dashboard (like the screenshot below).
+ ![onelogin-use-dashboard](../../images/auth/onelogin-use-dashboard.png)
diff --git a/docs/content/guides/auth/saml.md b/docs/content/guides/auth/saml.md
new file mode 100644
index 00000000..58a2ae45
--- /dev/null
+++ b/docs/content/guides/auth/saml.md
@@ -0,0 +1,97 @@
+# Authentication guide - SAML
+
+*Note:* This guide was written before the renaming. Just replace `HackMD` with `HedgeDoc` in your mind :smile: thanks!
+
+The basic procedure is the same as the case of OneLogin which is mentioned in [OneLogin-Guide](./saml-onelogin.md). If you want to match your IdP, you can use more configurations as below.
+
+- If your IdP accepts metadata XML of the service provider to ease configuration, use this url to download metadata XML.
+ - {{your-serverurl}}/auth/saml/metadata
+ - *Note:* If not accessible from IdP, download to local once and upload to IdP.
+
+- Change the value of `issuer`, `identifierFormat` to match your IdP.
+ - `issuer`: A unique id to identify the application to the IdP, which is the base URL of your HedgeDoc as default
+
+ - `identifierFormat`: A format of unique id to identify the user of IdP, which is the format based on email address as default. It is recommend that you use as below.
+ - urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress (default)
+ - urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
+
+ - `config.json`:
+ ```javascript
+ {
+ "production": {
+ "saml": {
+ /* omitted */
+ "issuer": "myhedgedoc"
+ "identifierFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+ }
+ }
+ }
+ ```
+
+ - environment variables
+ ```env
+ CMD_SAML_ISSUER=myhedgedoc
+ CMD_SAML_IDENTIFIERFORMAT=urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
+ ```
+
+- Change mapping of attribute names to customize the displaying user name and email address to match your IdP.
+ - `attribute`: A dictionary to map attribute names
+
+ - `attribute.id`: A primary key of user table for your HedgeDoc
+
+ - `attribute.username`: Attribute name of displaying user name on HedgeDoc
+
+ - `attribute.email`: Attribute name of email address, which will be also used for Gravatar
+ - *Note:* Default value of all attributes is NameID of SAML response, which is email address if `identifierFormat` is default.
+
+ - `config.json`:
+ ```javascript
+ {
+ "production": {
+ "saml": {
+ /* omitted */
+ "attribute": {
+ "id": "sAMAccountName",
+ "username": "displayName",
+ "email": "mail"
+ }
+ }
+ }
+ }
+ ```
+
+ - environment variables
+ ```sh
+ CMD_SAML_ATTRIBUTE_ID=sAMAccountName
+ CMD_SAML_ATTRIBUTE_USERNAME=nickName
+ CMD_SAML_ATTRIBUTE_EMAIL=mail
+ ```
+
+- If you want to control permission by group membership, add group attribute name and required group (allowed) or external group (not allowed).
+ - `groupAttribute`: An attribute name of group membership
+
+ - `requiredGroups`: Group names array for allowed access to HedgeDoc. Use vertical bar to separate for environment variables.
+
+ - `externalGroups`: Group names array for not allowed access to HedgeDoc. Use vertical bar to separate for environment variables.
+ - *Note:* Evaluates `externalGroups` first
+
+ - `config.json`:
+ ```javascript
+ {
+ "production": {
+ "saml": {
+ /* omitted */
+ "groupAttribute": "memberOf",
+ "requiredGroups": [ "hedgedoc-users", "board-members" ],
+ "externalGroups": [ "temporary-staff" ]
+ }
+ }
+ }
+ ```
+
+ - environment variables
+ ```sh
+ CMD_SAML_GROUPATTRIBUTE=memberOf
+ CMD_SAML_REQUIREDGROUPS=hedgedoc-users|board-members
+ CMD_SAML_EXTERNALGROUPS=temporary-staff
+ ```
diff --git a/docs/content/guides/auth/twitter.md b/docs/content/guides/auth/twitter.md
new file mode 100644
index 00000000..cbb8c865
--- /dev/null
+++ b/docs/content/guides/auth/twitter.md
@@ -0,0 +1,42 @@
+# Authentication guide - Twitter
+
+*Note:* This guide was written before the renaming. Just replace `HackMD` with `HedgeDoc` in your mind :smile: thanks!
+
+1. Sign-in or sign-up for a Twitter account
+
+2. Go to the Twitter Application management page [here](https://apps.twitter.com/)
+
+3. Click on the **Create New App** button to create a new Twitter app:
+ ![create-twitter-app](../../images/auth/create-twitter-app.png)
+
+4. Fill out the create application form, check the developer agreement box, and click **Create Your Twitter Application**
+ ![register-twitter-application](../../images/auth/register-twitter-application.png)
+
+ *Note:* you may have to register your phone number with Twitter to create a Twitter application
+
+ To do this Click your profile icon --> Settings and privacy --> Mobile --> Select Country/region --> Enter phone number --> Click Continue
+
+5. After you receive confirmation that the Twitter application was created, click **Keys and Access Tokens**
+ ![twitter-app-confirmation](../../images/auth/twitter-app-confirmation.png)
+
+6. Obtain your Twitter Consumer Key and Consumer Secret
+ ![twitter-app-keys](../../images/auth/twitter-app-keys.png)
+
+7. Add your Consumer Key and Consumer Secret to your `config.json` file or pass them as environment variables:
+ - `config.json`:
+ ```javascript
+ {
+ "production": {
+ "twitter": {
+ "consumerKey": "esTCJFXXXXXXXXXXXXXXXXXXX",
+ "consumerSecret": "zpCs4tU86pRVXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ }
+ }
+ }
+ ```
+
+ - environment variables:
+ ```sh
+ CMD_TWITTER_CONSUMERKEY=esTCJFXXXXXXXXXXXXXXXXXXX
+ CMD_TWITTER_CONSUMERSECRET=zpCs4tU86pRVXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ ```
diff --git a/docs/content/guides/migrate-etherpad.md b/docs/content/guides/migrate-etherpad.md
new file mode 100644
index 00000000..79784ef7
--- /dev/null
+++ b/docs/content/guides/migrate-etherpad.md
@@ -0,0 +1,128 @@
+# Pad migration guide from etherpad-lite
+
+The goal of this migration is to do a "dumb" import from all the pads in Etherpad, to notes in
+HedgeDoc. In particular, the url locations of the pads in Etherpad will be lost. Furthermore, any
+metadata in Etherpad, such as revisions, author data and also formatted text will not be migrated
+to HedgeDoc (only the plain text contents).
+
+Note that this guide is not really meant as a support guide. I migrated my own Etherpad to HedgeDoc,
+and it turned out to be quite easy in my opinion. In this guide I share my experience. Stuff may
+require some creativity to work properly in your case. When I wrote this guide, I was using
+[etherpad 1.7.0][] and [codimd 1.2.1][]. Good luck!
+
+## 0. Requirements
+
+- `curl`
+- running Etherpad server
+- running HedgeDoc server
+- [hedgedoc-cli][]
+
+## 1. Retrieve the list of pads
+
+First, compose a list of all the pads that you want to have migrated from your Etherpad. Other than
+the admin interface, Etherpad does not have a dedicated function to dump a list of all the pads.
+However, the Etherpad wiki explains how to list all the pads by [talking directly to the
+database][howtolistallpads].
+
+You will end up with a file containing a pad name on each line:
+
+```bash
+date-ideas
+groceries
+london
+weddingchecklist
+(...)
+```
+
+## 2. Run the migration
+
+Download [hedgedoc-cli][] and put the script in the same directory as the file containing the pad names.
+Add to this directory the file listed below, I called it `migrate-etherpad.sh`. Modify at least the
+configuration settings `ETHERPAD_SERVER` and `HEDGEDOC_SERVER`.
+
+```shell
+#!/bin/sh
+
+# migrate-etherpad.sh
+#
+# Description: Migrate pads from etherpad to HedgeDoc
+# Author: Daan Sprenkels <hello@dsprenkels.com>
+
+# This script uses the HedgeDoc command line script[1] to import a list of pads from
+# [1]: https://github.com/hedgedoc/cli/blob/master/bin/hedgedoc
+
+# The base url to where etherpad is hosted
+ETHERPAD_SERVER="https://etherpad.example.com"
+
+# The base url where HedgeDoc is hosted
+HEDGEDOC_SERVER="https://hedgedoc.example.com"
+
+# Write a list of pads and the urls which they were migrated to
+REDIRECTS_FILE="redirects.txt"
+
+
+# Fail if not called correctly
+if (( $# != 1 )); then
+ echo "Usage: $0 PAD_NAMES_FILE"
+ exit 2
+fi
+
+# Do the migration
+for PAD_NAME in $1; do
+ # Download the pad
+ PAD_FILE="$(mktemp)"
+ curl "$ETHERPAD_SERVER/p/$PAD_NAME/export/txt" >"$PAD_FILE"
+
+ # Import the pad into HedgeDoc
+ OUTPUT="$(./hedgedoc import "$PAD_FILE")"
+ echo "$PAD_NAME -> $OUTPUT" >>"$REDIRECTS_FILE"
+done
+```
+
+Call this file like this:
+
+```shell
+./migrate-etherpad.sh pad_names.txt
+```
+
+This will download all the pads in `pad_names.txt` and put them on HedgeDoc. They will get assigned
+random ids, so you won't be able to find them. The script will save the mappings to a file though
+(in my case `redirects.txt`). You can use this file to redirect your users when they visit your
+etherpad using a `301 Permanent Redirect` status code (see the next section).
+
+## 3. Setup redirects (optional)
+
+I got a `redirects.txt` file that looked a bit like this:
+
+```log
+date-ideas -> Found. Redirecting to https://hedgedoc.example.com/mPt0KfiKSBOTQ3mNcdfn
+groceries -> Found. Redirecting to https://hedgedoc.example.com/UukqgwLfhYyUUtARlcJ2_y
+london -> Found. Redirecting to https://hedgedoc.example.com/_d3wa-BE8t4Swv5w7O2_9R
+weddingchecklist -> Found. Redirecting to https://hedgedoc.example.com/XcQGqlBjl0u40wfT0N8TzQ
+(...)
+```
+
+Using some `sed` magic, I changed it to an nginx config snippet:
+
+```nginx
+location = /p/date-ideas {
+ return 301 https://hedgedoc.example.com/mPt0M1KfiKSBOTQ3mNcdfn;
+}
+location = /p/groceries {
+ return 301 https://hedgedoc.example.com/UukqgwLfhYyUUtARlcJ2_y;
+}
+location = /p/london {
+ return 301 https://hedgedoc.example.com/_d3wa-BE8t4Swv5w7O2_9R;
+}
+location = /p/weddingchecklist {
+ return 301 https://hedgedoc.example.com/XcQGqlBjl0u40wfT0N8TzQ;
+}
+```
+
+I put this file into my `etherpad.example.com` nginx config, such that all the users would be
+redirected accordingly.
+
+[etherpad 1.7.0]: https://github.com/ether/etherpad-lite/tree/1.7.0
+[codimd 1.2.1]: https://github.com/hedgedoc/hedgedoc/tree/1.2.1
+[hedgedoc-cli]: https://github.com/hedgedoc/cli/blob/master/bin/hedgedoc
+[howtolistallpads]: https://github.com/ether/etherpad-lite/wiki/How-to-list-all-pads/49701ecdcbe07aea7ad27ffa23aed0d99c2e17db
diff --git a/docs/content/guides/migrations-and-breaking-changes.md b/docs/content/guides/migrations-and-breaking-changes.md
new file mode 100644
index 00000000..bbc320b1
--- /dev/null
+++ b/docs/content/guides/migrations-and-breaking-changes.md
@@ -0,0 +1,55 @@
+# Migrations and Notable Changes
+
+## Migrating to 1.4.0
+
+We dropped support for node 6 with this version. If you have any trouble running this version, please double check that you are running at least node 8!
+
+## Migrating to 1.3.2
+
+This is not a breaking change, but to stay up to date with the community
+repository, you may need to update a few urls. This is not a breaking change.
+
+See more at [issue #10](https://github.com/hedgedoc/hedgedoc/issues/10)
+
+### Native setup using git
+
+Change the upstream remote using `git remote set-url origin https://github.com/hedgedoc/hedgedoc.git`.
+
+### Docker
+
+When you use our [container repository](https://github.com/hedgedoc/container)
+(which was previously `hedgedoc-container`) all you can simply run `git pull` and
+your `docker-compose.yml` will be updated.
+
+When you setup things yourself, make sure you use the new image:
+[`quay.io/hedgedoc/hedgedoc`](https://quay.io/repository/hedgedoc/hedgedoc?tab=tags).
+
+### Heroku
+
+All you need to do is [disconnect GitHub](https://devcenter.heroku.com/articles/github-integration#disconnecting-from-github)
+and [reconnect it](https://devcenter.heroku.com/articles/github-integration#enabling-github-integration)
+with this new repository.
+
+Or you can use our Heroku button and redeploy your instance and link the old
+database again.
+
+## Migrating to 1.1.0
+
+We deprecated the older lower case config style and moved on to camel case style. Please have a look at the current `config.json.example` and check the warnings on startup.
+
+*Notice: This is not a breaking change right now but will be in the future*
+
+## Migrating to 0.5.0
+
+[migration-to-0.5.0 migration tool](https://github.com/hackmdio/migration-to-0.5.0)
+
+We don't use LZString to compress socket.io data and DB data after version 0.5.0.
+Please run the migration tool if you're upgrading from the old version.
+
+## Migrating to 0.4.0
+
+[migration-to-0.4.0 migration tool](https://github.com/hackmdio/migration-to-0.4.0)
+
+We've dropped MongoDB after version 0.4.0.
+So here is the migration tool for you to transfer the old DB data to the new DB.
+This tool is also used for official service.
diff --git a/docs/content/guides/minio-image-upload.md b/docs/content/guides/minio-image-upload.md
new file mode 100644
index 00000000..41d9b14e
--- /dev/null
+++ b/docs/content/guides/minio-image-upload.md
@@ -0,0 +1,94 @@
+# Minio Guide for HedgeDoc
+
+*Note:* This guide was written before the renaming. Just replace `HackMD` with `HedgeDoc` in your mind :smile: thanks!
+
+1. First of all you need to setup Minio itself.
+
+ Please refer to the [official Minio docs](https://docs.minio.io/) for an
+ production setup.
+
+ For checking it out and development purposes a non-persistent setup is enough:
+ ```sh
+ docker run --name test-minio --rm -d -p 9000:9000 minio/minio server /data
+ ```
+
+ *Please notice this is not for productive use as all your data gets lost
+ when you stop this container*
+
+2. Next step is to get the credentials form the container:
+
+ ```sh
+ docker logs test-minio
+ ```
+
+ ![docker logs](../images/minio-image-upload/docker-logs.png)
+
+3. Open <http://localhost:9000> and login with the shown credentials.
+
+ ![minio default view](../images/minio-image-upload/default-view.png)
+
+4. Create a bucket for HedgeDoc
+
+ ![minio create bucket](../images/minio-image-upload/create-bucket.png)
+
+5. Add a policy for the prefix `uploads` and make it read-only.
+
+ ![minio edit policy](../images/minio-image-upload/open-edit-policy.png)
+ *Open policy editor*
+
+ ![minio policy adding](../images/minio-image-upload/create-policy.png)
+ *Add policy for uploads*
+
+6. Set credentials and configs for Minio in HedgeDoc's `config.json`
+
+ ```JSON
+ "minio": {
+ "accessKey": "888MXJ7EP4XXXXXXXXX",
+ "secretKey": "yQS2EbM1Y6IJrp/1BUKWq2/XXXXXXXXXXXXXXX",
+ "endPoint": "localhost",
+ "port": 9000,
+ "secure": false
+ }
+ ```
+ *You have to use different values for `endpoint` and `port` for a production
+ setup. Keep in mind the `endpoint`-address has to be public accessible from
+ your browser.*
+
+7. Set bucket name
+
+ ```JSON
+ "s3bucket": "hedgedoc"
+ ```
+
+8. Set upload type.
+
+ ```JSON
+ "imageuploadtype": "minio"
+ ```
+
+9. Review your config.
+
+ ```json
+ {
+ // all your other config…
+ "minio": {
+ "accessKey": "888MXJ7EP4XXXXXXXXX",
+ "secretKey": "yQS2EbM1Y6IJrp/1BUKWq2/XXXXXXXXXXXXXXX",
+ "endPoint": "localhost",
+ "port": 9000,
+ "secure": false
+ },
+ "s3bucket": "hedgedoc",
+ "imageuploadtype": "minio"
+ }
+ ```
+
+10. If you were using filesystem before
+
+and you want to migrate assets to minio.
+
+You could use a convenience script located in `bin/migrate_from_fs_to_minio`.
+
+Be careful, read carefully what it does, it was not tested in all environments.
+
+Take it as an inspiration to make your own migration script. \ No newline at end of file
diff --git a/docs/content/guides/providing-terms.md b/docs/content/guides/providing-terms.md
new file mode 100644
index 00000000..54a792f6
--- /dev/null
+++ b/docs/content/guides/providing-terms.md
@@ -0,0 +1,25 @@
+# How to set up your terms of use
+
+## Setup your terms of use
+
+To setup your terms of use, you need to provide a document called `terms-of-use.md` which contains them. Of course written in Markdown.
+
+It has to be provided under `./public/docs/` and will be automatically turned into a HedgeDoc document. It will also automatically updated as soon as you change the document on disk.
+
+As soon as the file exists a link will show up in the bottom part along with the release notes and link to them.
+
+## Setup your privacy policy
+
+To add a privacy policy you can use the same technique as for the terms of use. The main difference is that the document is called `privacy.md`.
+
+See our example file `./public/docs/privacy.md.example` container some useful hints for writing your own privacy policy.
+
+As with the terms of use, a link to the privacy notices will show up in the area where the release notes are provided on the index page.
+
+## Setup your imprint
+
+To add an imprint you can use the same technique as for the terms of use. The main difference is that the document is called `imprint.md`.
+
+It has to be provided under `./public/docs/` and will be automatically turned into a HedgeDoc document. It will also automatically updated as soon as you change the document on disk.
+
+As with the terms of use, a link to the imprint will show up in the area where the release notes are provided on the index page.
diff --git a/docs/content/guides/s3-image-upload.md b/docs/content/guides/s3-image-upload.md
new file mode 100644
index 00000000..3b041066
--- /dev/null
+++ b/docs/content/guides/s3-image-upload.md
@@ -0,0 +1,77 @@
+# Guide - Setup HedgeDoc S3 image upload
+
+**Note:** *This guide was written before the renaming. Just replace `HackMD` with `HedgeDoc` in your mind :smile: thanks!*
+
+1. Go to [AWS S3 console](https://console.aws.amazon.com/s3/home) and create a new bucket.
+ ![create-bucket](../images/s3-image-upload/create-bucket.png)
+
+2. Click on bucket, select **Properties** on the side panel, and find **Permission** section. Click **Edit bucket policy**.
+ ![bucket-property](../images/s3-image-upload/bucket-property.png)
+
+3. Enter the following policy, replace `bucket_name` with your bucket name:
+ ![bucket-policy-editor](../images/s3-image-upload/bucket-policy-editor.png)
+
+ ```json
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": "*",
+ "Action": "s3:GetObject",
+ "Resource": "arn:aws:s3:::bucket_name/uploads/*"
+ }
+ ]
+ }
+ ```
+
+4. Go to IAM console and create a new IAM user. Remember your user credentials(`key`/`access token`)
+
+5. Enter user page, select **Permission** tab, look at **Inline Policies** section, and click **Create User Policy**
+ ![iam-user](../images/s3-image-upload/iam-user.png)
+
+6. Select **Custom Policy**
+ ![custom-policy](../images/s3-image-upload/custom-policy.png)
+
+7. Enter the following policy, replace `bucket_name` with your bucket name:
+ ![review-policy](../images/s3-image-upload/review-policy.png)
+
+ ```json
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "s3:*"
+ ],
+ "Resource": [
+ "arn:aws:s3:::bucket_name/uploads/*"
+ ]
+ }
+ ]
+ }
+ ```
+
+8. Edit `config.json` and set following keys:
+
+ ```javascript
+ {
+ "production": {
+ ...
+ "imageuploadtype": "s3",
+ "s3": {
+ "accessKeyId": "YOUR_S3_ACCESS_KEY_ID",
+ "secretAccessKey": "YOUR_S3_ACCESS_KEY",
+ "region": "YOUR_S3_REGION" // example: ap-northeast-1
+ },
+ "s3bucket": "YOUR_S3_BUCKET_NAME"
+ }
+ }
+ ```
+
+9. In additional to edit `config.json` directly, you could also try [environment variables](../configuration.md).
+
+## Related Tools
+
+- [AWS Policy Generator](http://awspolicygen.s3.amazonaws.com/policygen.html)