diff --git a/README.md b/README.md index 0ebceaab3..e9017c883 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,9 @@ which you are very welcome to join. Licensed under AGPLv3. For our list of contributors, see [AUTHORS](AUTHORS). +The license does not include the HedgeDoc logo, whose terms of usage can be found in +the [github repository](https://github.com/hedgedoc/hedgedoc-logo). + [matrix.org-image]: https://img.shields.io/matrix/hedgedoc:matrix.org?logo=matrix&server_fqdn=matrix.org [matrix.org-url]: https://chat.hedgedoc.org @@ -51,15 +54,9 @@ Licensed under AGPLv3. For our list of contributors, see [AUTHORS](AUTHORS). [poeditor-image]: https://img.shields.io/badge/POEditor-translate-blue.svg [poeditor-url]: https://poeditor.com/join/project/1OpGjF2Jir - [hedgedoc-demo]: https://demo.hedgedoc.org - [hedgedoc-demo-features]: https://demo.hedgedoc.org/features - [hedgedoc-community]: https://community.hedgedoc.org - [hedgedoc-community-calls]: https://community.hedgedoc.org/t/codimd-community-call/19 - [social-mastodon]: https://social.hedgedoc.org/mastodon - [social-mastodon-image]: https://img.shields.io/mastodon/follow/49593?domain=https%3A%2F%2Fsocial.snopyta.org&style=social diff --git a/docs/configuration-config-file.md b/docs/configuration-config-file.md deleted file mode 100644 index db00e3a82..000000000 --- a/docs/configuration-config-file.md +++ /dev/null @@ -1,189 +0,0 @@ -Configuration Using Config file -=== - -You can choose to configure CodiMD with either a config file or with -[environment variables](configuration-env-vars.md). The config file is processed -in [`lib/config/index.js`](../lib/config/index.js) - so this is the first -place to look if anything is missing not obvious from this document. The -default values are defined in [`lib/config/default.js`](../lib/config/default.js), -in case you wonder if you even need to override it. - -Environment variables take precedence over configurations from the config files. -To get started, it is a good idea to take the `config.json.example` and copy it -to `config.json` before filling in your own details. - - -## Node.JS - -| variables | example values | description | -| --------- | ------ | ----------- | -| `debug` | `true` or `false` | set debug mode, show more logs | - - -## CodiMD basics - -| variables | example values | description | -| --------- | ------ | ----------- | -| `db` | `{ "dialect": "sqlite", "storage": "./db.codimd.sqlite" }` | set the db configs, [see more here](http://sequelize.readthedocs.org/en/latest/api/sequelize/) | -| `dbURL` | `mysql://localhost:3306/database` | Set the db in URL style. If set, then the relevant `db` config entries will be overridden. | -| `forbiddenNoteIDs` | `['robots.txt']` | disallow creation of notes, even if `allowFreeUrl` is `true` | -| `loglevel` | `info` | Defines what kind of logs are provided to stdout. Available options: `debug`, `verbose`, `info`, `warn`, `error` | -| `imageUploadType` | `imgur`, `s3`, `minio`, `azure`, `lutim` or `filesystem`(default) | Where to upload images. For S3, see our Image Upload Guides for [S3](guides/s3-image-upload.md) or [MinIO](guides/minio-image-upload.md)| -| `sourceURL` | `https://github.com/codimd/server/tree/` | Provides the link to the source code of CodiMD on the entry page (Please, make sure you change this when you run a modified version) | -| `staticCacheTime` | `1 * 24 * 60 * 60 * 1000` | static file cache time | -| `tooBusyLag` | `70` | CPU time for one event loop tick until node throttles connections. (milliseconds) | -| `heartbeatInterval` | `5000` | socket.io heartbeat interval | -| `heartbeatTimeout` | `10000` | socket.io heartbeat timeout | -| `documentMaxLength` | `100000` | note max length | - - -## CodiMD paths stuff - -these are rarely used for various reasons. - -| variables | example values | description | -| --------- | ------ | ----------- | -| `defaultNotePath` | `./public/default.md` | default note file path1, empty notes will be created with this template. | -| `dhParamPath` | `./cert/dhparam.pem` | SSL dhparam path1 (only need when you set `useSSL`) | -| `sslCAPath` | `['./cert/COMODORSAAddTrustCA.crt']` | SSL ca chain1 (only need when you set `useSSL`) | -| `sslCertPath` | `./cert/codimd_io.crt` | SSL cert path1 (only need when you set `useSSL`) | -| `sslKeyPath` | `./cert/client.key` | SSL key path1 (only need when you set `useSSL`) | -| `tmpPath` | `./tmp/` | temp directory path1 | -| `docsPath` | `./public/docs` | docs directory path1 | -| `viewPath` | `./public/views` | template directory path1 | -| `uploadsPath` | `./public/uploads` | uploads directory1 - needs to be persistent when you use imageUploadType `filesystem` | -| `localesPath` | `./locales` | directory for translations1 | - - -## CodiMD Location - -| variables | example values | description | -| --------- | ------ | ----------- | -| `domain` | `localhost` | domain name | -| `urlPath` | `codimd` | sub URL path, like `www.example.com/` | -| `host` | `localhost` | interface/ip to listen on | -| `port` | `80` | port to listen on | -| `path` | `/var/run/codimd.sock` | path to UNIX domain socket to listen on (if specified, `host` and `port` are ignored) | -| `protocolUseSSL` | `true` or `false` | set to use SSL protocol for resources path (only applied when domain is set) | -| `useSSL` | `true` or `false` | set to use SSL server (if `true`, will auto turn on `protocolUseSSL`) | -| `urlAddPort` | `true` or `false` | set to add port on callback URL (ports `80` or `443` won't be applied) (only applied when domain is set) | -| `allowOrigin` | `['localhost']` | domain name whitelist | - - -## CSP and HSTS - -| variables | example values | description | -| --------- | ------ | ----------- | -| `hsts` | `{"enable": true, "maxAgeSeconds": 31536000, "includeSubdomains": true, "preload": true}` | [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) options to use with HTTPS (default is the example value, max age is a year) | -| `csp` | `{"enable": true, "directives": {"scriptSrc": "trustworthy-scripts.example.com"}, "upgradeInsecureRequests": "auto", "addDefaults": true}` | Configures [Content Security Policy](https://helmetjs.github.io/docs/csp/). Directives are passed to Helmet - see [their documentation](https://helmetjs.github.io/docs/csp/) for more information on the format. Some defaults are added to the configured values so that the application doesn't break. To disable this behaviour, set `addDefaults` to `false`. Further, if `usecdn` is on, some CDN locations are allowed too. By default (`auto`), insecure (HTTP) requests are upgraded to HTTPS via CSP if `useSSL` is on. To change this behaviour, set `upgradeInsecureRequests` to either `true` or `false`. | - -## Privacy and External Requests - -| variables | example values | description | -| --------- | ------ | ----------- | -| `allowGravatar` | `true` or `false` | set to `false` to disable [Libravatar](https://www.libravatar.org/) as profile picture source on your instance. Libravatar is a federated open-source alternative to Gravatar. | -| `useCDN` | `true` or `false` | set to use CDN resources or not (default is `false`) | - -## Users and Privileges - -| variables | example values | description | -| --------- | ------ | ----------- | -| `allowAnonymous` | `true` or `false` | Set to allow anonymous usage (default is `true`). | -| `allowAnonymousEdits` | `true` or `false` | If `allowAnonymous` is `true`: allow users to select `freely` permission, allowing guests to edit existing notes (default is `false`). | -| `allowFreeURL` | `true` or `false` | Set to allow new note creation by accessing a nonexistent note URL. This is the behavior familiar from [Etherpad](https://github.com/ether/etherpad-lite). | -| `defaultPermission` | `freely`, `editable`, `limited`, `locked`, `protected` or `private` | Set notes default permission (only applied on signed-in users). | -| `sessionName` | `connect.sid` | Cookie session name. | -| `sessionLife` | `14 * 24 * 60 * 60 * 1000` (14 days) | Cookie session life time in milliseconds. | -| `sessionSecret` | `secret` | Cookie session secret. If none is set, one will randomly generated on each startup, meaning all your users will be logged out. | - - -## Login methods - -### Email (local account) - -| variables | example values | description | -| --------- | ------ | ----------- | -| `email` | `true` or `false` | Set to allow email sign-in. The default is `true`. | -| `allowEmailRegister` | `true` or `false` | Set to allow registration of new accounts using an email address. If set to `false`, you can still create accounts using the command line - see `bin/manage_users` for details (In production mode, remember to run it with `NODE_ENV` set as `production` in the enviroment). This setting has no effect if `email` is `false`. The default for `allowEmailRegister` is `true`. | - -### Dropbox Login - -| variables | example values | description | -| --------- | ------ | ----------- | -| `dropbox` | `{clientID: ..., clientSecret: ...}` | An object containing the client ID and the client secret obtained by the [Dropbox developer tools](https://www.dropbox.com/developers/apps) | - -### Facebook Login - -| variables | example values | description | -| --------- | ------ | ----------- | -| `facebook` | `{clientID: ..., clientSecret: ...}` | An object containing the client ID and the client secret obtained by the [Facebook app console](https://developers.facebook.com/apps) | - -### GitHub Login - -| variables | example values | description | -| --------- | ------ | ----------- | -| `github` | `{clientID: ..., clientSecret: ...}` | An object containing the client ID and the client secret obtained by the GitHub developer page. For more details have a look at the [GitHub auth guide](guides/auth/github.md). | - -### GitLab Login - -| variables | example values | description | -| --------- | ------ | ----------- | -| `gitlab` | `{baseURL: ..., scope: ..., version: ..., clientID: ..., clientSecret: ...}` | An object containing your GitLab application data. Refer to the [GitLab guide](guides/auth/gitlab-self-hosted.md) for more details! | - -### Google Login - -| variables | example values | description | -| --------- | ------ | ----------- | -| `google` | `{clientID: ..., clientSecret: ..., hostedDomain: ...}` | An object containing the client ID and the client secret obtained by the [Google API console](https://console.cloud.google.com/apis) | - -### LDAP Login - -| variables | example values | description | -| --------- | ------ | ----------- | -| `ldap` | `{providerName: ..., url: ..., bindDn: ..., bindCredentials: ..., searchBase: ..., searchFilter: ..., searchAttributes: ..., usernameField: ..., useridField: ..., starttls: ..., tlsca: ...}` | An object detailing the LDAP connection. Refer to the [LDAP-AD guide](guides/auth/ldap-AD.md) for more details! | - -### OAuth2 Login - -| variables | example values | description | -| --------- | ------ | ----------- | -| `oauth2` | `{baseURL: ..., userProfileURL: ..., userProfileUsernameAttr: ..., userProfileDisplayNameAttr: ..., userProfileEmailAttr: ..., tokenURL: ..., authorizationURL: ..., clientID: ..., clientSecret: ..., scope: ...}` | An object detailing your OAuth2 provider. Refer to the [Mattermost](guides/auth/mattermost-self-hosted.md) or [Nextcloud](guides/auth/nextcloud.md) examples for more details!| - -### SAML Login - -| variables | example values | description | -| --------- | ------ | ----------- | -| `saml` | `{idpSsoUrl: ..., idpCert: ..., issuer: ..., identifierFormat: ..., disableRequestedAuthnContext: ..., groupAttribute: ..., externalGroups: [], requiredGroups: [], attribute: {id: ..., username: ..., email: ...}}` | An object detailing your SAML provider. Refer to the [OneLogin](guides/auth/saml-onelogin.md) and [SAML](guides/auth/saml.md) guides for more details! | - -### Twitter Login - -| variables | example values | description | -| --------- | ------ | ----------- | -| `twitter` | `{consumerKey: ..., consumerSecret: ...}` | An object containing the consumer key and secret obtained by the [Twitter developer tools](https://developer.twitter.com/apps). For more details have a look at the [Twitter auth guide](guides/auth/twitter.md) | - -## Upload Storage - -Most of these have never been documented for the config.json, feel free to expand these - - -### Amazon S3 - -| variables | example values | description | -| --------- | ------ | ----------- | -| `s3` | `{ "accessKeyId": "YOUR_S3_ACCESS_KEY_ID", "secretAccessKey": "YOUR_S3_ACCESS_KEY", "region": "YOUR_S3_REGION" }` | When `imageuploadtype` be set to `s3`, you would also need to setup this key, check our [S3 Image Upload Guide](guides/s3-image-upload.md) | -| `s3bucket` | `YOUR_S3_BUCKET_NAME` | bucket name when `imageUploadType` is set to `s3` or `minio` | - -### Azure Blob Storage -### Imgur -### MinIO - -| variables | example values | description | -| --------- | ------ | ----------- | -| `minio` | `{ "accessKey": "YOUR_MINIO_ACCESS_KEY", "secretKey": "YOUR_MINIO_SECRET_KEY", "endpoint": "YOUR_MINIO_HOST", port: 9000, secure: true }` | When `imageUploadType` is set to `minio`, you need to set this key. Also check out our [Minio Image Upload Guide](guides/minio-image-upload.md) | - -### Lutim - -| variables | example values | description | -| --------- | ------ | ----------- | -|`lutim`| `{"url": "YOUR_LUTIM_URL"}`| When `imageUploadType` is set to `lutim`, you can setup the lutim url| - -1: relative paths are based on CodiMD's base directory diff --git a/docs/configuration-env-vars.md b/docs/configuration-env-vars.md deleted file mode 100644 index 999e43057..000000000 --- a/docs/configuration-env-vars.md +++ /dev/null @@ -1,248 +0,0 @@ -Configuration Using Environment variables -=== - -You can choose to configure CodiMD with either a -[config file](configuration-config-file.md) or with environment variables. -Environment variables are processed in -[`lib/config/environment.js`](../lib/config/environment.js) - so this is the first -place to look if anything is missing not obvious from this document. The -default values are defined in [`lib/config/default.js`](../lib/config/default.js), -in case you wonder if you even need to override it. - -Environment variables take precedence over configurations from the config files. -They generally start with `CMD_` for our own options, but we also list -node-specific options you can configure this way. - - -## Node.JS - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `NODE_ENV` | `production` or `development` | set current environment (will apply corresponding settings in the `config.json`) | -| `DEBUG` | `true` or `false` | set debug mode; show more logs | - - -## CodiMD basics - -defaultNotePath can't be set from env-vars - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_CONFIG_FILE` | `/path/to/config.json` | optional override for the path to CodiMD's config file | -| `CMD_DB_URL` | `mysql://localhost:3306/database` | Set the db in URL style. If set, then the relevant `db` config entries will be overridden. | -| `CMD_LOGLEVEL` | `info`, `debug` ... | Defines what kind of logs are provided to stdout. | -| `CMD_FORBIDDEN_NOTE_IDS` | `'robots.txt'` | disallow creation of notes, even if `CMD_ALLOW_FREEURL` is `true` | -| `CMD_IMAGE_UPLOAD_TYPE` | `imgur`, `s3`, `minio`, `lutim` or `filesystem` | Where to upload images. For S3, see our Image Upload Guides for [S3](guides/s3-image-upload.md) or [Minio](guides/minio-image-upload.md), also there's a whole section on their respective env vars below. | -| `CMD_SOURCE_URL` | `https://github.com/codimd/server/tree/` | Provides the link to the source code of CodiMD on the entry page (Please, make sure you change this when you run a modified version) | -| `CMD_TOOBUSY_LAG` | `70` | CPU time for one event loop tick until node throttles connections. (milliseconds) | - - -## CodiMD Location - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_DOMAIN` | `codimd.org` | domain name | -| `CMD_URL_PATH` | `codimd` | If CodiMD is run from a subdirectory like `www.example.com/` | -| `CMD_HOST` | `localhost` | interface/ip to listen on | -| `CMD_PORT` | `80` | port to listen on | -| `CMD_PATH` | `/var/run/codimd.sock` | path to UNIX domain socket to listen on (if specified, `CMD_HOST` and `CMD_PORT` are ignored) | -| `CMD_PROTOCOL_USESSL` | `true` or `false` | set to use SSL protocol for resources path (only applied when domain is set) | -| `CMD_URL_ADDPORT` | `true` or `false` | set to add port on callback URL (ports `80` or `443` won't be applied) (only applied when domain is set) | -| `CMD_ALLOW_ORIGIN` | `localhost, codimd.org` | domain name whitelist (use comma to separate) | - - -## CSP and HSTS - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_CSP_ENABLE` | `true` | whether to enable Content Security Policy (directives cannot be configured with environment variables) | -| `CMD_CSP_REPORTURI` | `https://.report-uri.com/r/d/csp/enforce` | Allows to add a URL for CSP reports in case of violations | -| `CMD_HSTS_ENABLE` | ` true` | set to enable [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) if HTTPS is also enabled (default is ` true`) | -| `CMD_HSTS_INCLUDE_SUBDOMAINS` | `true` | set to include subdomains in HSTS (default is `true`) | -| `CMD_HSTS_MAX_AGE` | `31536000` | max duration in seconds to tell clients to keep HSTS status (default is a year) | -| `CMD_HSTS_PRELOAD` | `true` | whether to allow preloading of the site's HSTS status (e.g. into browsers) | - - -## Privacy and External Requests - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_ALLOW_GRAVATAR` | `true` or `false` | set to `false` to disable [Libravatar](https://www.libravatar.org/) as profile picture source on your instance. Libravatar is a federated open-source alternative to Gravatar. | -| `CMD_USECDN` | `true` or `false` | set to use CDN resources or not| - - -## Users and Privileges - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_ALLOW_ANONYMOUS` | `true` or `false` | Set to allow anonymous usage (default is `true`). | -| `CMD_ALLOW_ANONYMOUS_EDITS` | `true` or `false` | If `allowAnonymous` is `false`: allow users to select `freely` permission, allowing guests to edit existing notes (default is `true`). | -| `CMD_ALLOW_FREEURL` | `true` or `false` | Set to allow new note creation by accessing a nonexistent note URL. This is the behavior familiar from [Etherpad](https://github.com/ether/etherpad-lite). | -| `CMD_DEFAULT_PERMISSION` | `freely`, `editable`, `limited`, `locked`, `protected` or `private` | Set notes default permission (only applied on signed-in users). | -| `CMD_SESSION_LIFE` | `1209600000` (14 days) | Cookie session life time in milliseconds. | -| `CMD_SESSION_SECRET` | no example | Secret used to sign the session cookie. If none is set, one will randomly generated on each startup, meaning all your users will be logged out. | - - -## Login methods - -### Email (local account) - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_EMAIL` | `true` or `false` | Set to allow email sign-in. The default is `true`. | -| `CMD_ALLOW_EMAIL_REGISTER` | `true` or `false` | Set to allow registration of new accounts using an email address. If set to `false`, you can still create accounts using the command line - see `bin/manage_users` for details (In production mode, remember to run it with `NODE_ENV` set as `production` in the enviroment). This setting has no effect if `CMD_EMAIL` is `false`. The default for `CMD_ALLOW_EMAIL_REGISTER` is `true`. | - - -### Dropbox Login - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_DROPBOX_CLIENTID` | no example | Dropbox API client id | -| `CMD_DROPBOX_CLIENTSECRET` | no example | Dropbox API client secret | - - -### Facebook Login - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_FACEBOOK_CLIENTID` | no example | Facebook API client id | -| `CMD_FACEBOOK_CLIENTSECRET` | no example | Facebook API client secret | - - -### GitHub Login - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_GITHUB_CLIENTID` | no example | GitHub API client id | -| `CMD_GITHUB_CLIENTSECRET` | no example | GitHub API client secret | - - -### GitLab Login - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_GITLAB_SCOPE` | `read_user` or `api` | GitLab API requested scope (default is `api`) (GitLab snippet import/export need `api` scope) | -| `CMD_GITLAB_BASEURL` | no example | GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional) | -| `CMD_GITLAB_CLIENTID` | no example | GitLab API client id | -| `CMD_GITLAB_CLIENTSECRET` | no example | GitLab API client secret | -| `CMD_GITLAB_VERSION` | no example | GitLab API version (v3 or v4) | - - -### Google Login - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_GOOGLE_CLIENTID` | no example | Google API client id | -| `CMD_GOOGLE_CLIENTSECRET` | no example | Google API client secret | -| `CMD_GOOGLE_HOSTEDDOMAIN` | `example.com` | Provided only if the user belongs to a hosted domain. default is `undefined` | - - -### LDAP Login - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_LDAP_URL` | `ldap://example.com` | URL of LDAP server | -| `CMD_LDAP_BINDDN` | no example | bindDn for LDAP access | -| `CMD_LDAP_BINDCREDENTIALS` | no example | bindCredentials for LDAP access | -| `CMD_LDAP_SEARCHBASE` | `o=users,dc=example,dc=com` | LDAP directory to begin search from | -| `CMD_LDAP_SEARCHFILTER` | `(uid={{username}})` | LDAP filter to search with | -| `CMD_LDAP_SEARCHATTRIBUTES` | `displayName, mail` | LDAP attributes to search with (use comma to separate) | -| `CMD_LDAP_USERIDFIELD` | `uidNumber` or `uid` or `sAMAccountName` | The LDAP field which is used uniquely identify a user on CodiMD | -| `CMD_LDAP_USERNAMEFIELD` | Fallback to userid | The LDAP field which is used as the username on CodiMD | -| `CMD_LDAP_TLS_CA` | `server-cert.pem, root.pem` | Root CA for LDAP TLS in PEM format (use comma to separate) | -| `CMD_LDAP_PROVIDERNAME` | `My institution` | Optional name to be displayed at login form indicating the LDAP provider | - - -### OAuth2 Login - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_OAUTH2_USER_PROFILE_URL` | `https://example.com` | Where to retrieve information about a user after successful login. Needs to output JSON. (no default value) Refer to the [Mattermost](guides/auth/mattermost-self-hosted.md) or [Nextcloud](guides/auth/nextcloud.md) examples for more details on all of the `CMD_OAUTH2...` options. | -| `CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR` | `name` | where to find the username in the JSON from the user profile URL. (no default value)| -| `CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR` | `display-name` | where to find the display-name in the JSON from the user profile URL. (no default value) | -| `CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR` | `email` | where to find the email address in the JSON from the user profile URL. (no default value) | -| `CMD_OAUTH2_TOKEN_URL` | `https://example.com` | sometimes called token endpoint, please refer to the documentation of your OAuth2 provider (no default value) | -| `CMD_OAUTH2_AUTHORIZATION_URL` | `https://example.com` | authorization URL of your provider, please refer to the documentation of your OAuth2 provider (no default value) | -| `CMD_OAUTH2_CLIENT_ID` | `afae02fckafd...` | you will get this from your OAuth2 provider when you register CodiMD as OAuth2-client, (no default value) | -| `CMD_OAUTH2_CLIENT_SECRET` | `afae02fckafd...` | you will get this from your OAuth2 provider when you register CodiMD as OAuth2-client, (no default value) | -| `CMD_OAUTH2_SCOPE` | `openid email profile` | The requested OAuth2/OIDC scopes, which are privileges that CodiMD can exercise on behalf of the user. Default is `openid email profile`, in order to retrieve user email/profile information via the user profile URL. | -| `CMD_OAUTH2_PROVIDERNAME` | `My institution` | Optional name to be displayed at login form indicating the oAuth2 provider | - - -### SAML Login - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_SAML_IDPSSOURL` | `https://idp.example.com/sso` | authentication endpoint of IdP. for details, see [guide](guides/auth/saml-onelogin.md). | -| `CMD_SAML_IDPCERT` | `/path/to/cert.pem` | certificate file path of IdP in PEM format | -| `CMD_SAML_ISSUER` | no example | Issuer to supply to identity provider (optional, default: `serverURL` config)" | -| `CMD_SAML_DISABLEREQUESTEDAUTHNCONTEXT` | `true` or `false` | true to allow any authentication method, false restricts to password authentication (PasswordProtectedTransport) method (default: false) | -| `CMD_SAML_IDENTIFIERFORMAT` | no example | name identifier format (optional, default: `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`) | -| `CMD_SAML_GROUPATTRIBUTE` | `memberOf` | attribute name for group list (optional) | -| `CMD_SAML_REQUIREDGROUPS` | `codimd-users` | group names that allowed (use vertical bar to separate) (optional) | -| `CMD_SAML_EXTERNALGROUPS` | `Temporary-staff` | group names that not allowed (use vertical bar to separate) (optional) | -| `CMD_SAML_ATTRIBUTE_ID` | `sAMAccountName` | attribute map for `id` (optional, default: NameID of SAML response) | -| `CMD_SAML_ATTRIBUTE_USERNAME` | `mailNickname` | attribute map for `username` (optional, default: NameID of SAML response) | -| `CMD_SAML_ATTRIBUTE_EMAIL` | `mail` | attribute map for `email` (optional, default: NameID of SAML response if `CMD_SAML_IDENTIFIERFORMAT` is default) | - - -### Twitter Login - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_TWITTER_CONSUMERKEY` | no example | Twitter API consumer key | -| `CMD_TWITTER_CONSUMERSECRET` | no example | Twitter API consumer secret | - - -## Upload Storage - -These are only relevant when they are also configured in sync with their -`CMD_IMAGE_UPLOAD_TYPE`. Also keep in mind, that `filesystem` is available, so -you don't have to use either of these. - - -### Amazon S3 - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_S3_ACCESS_KEY_ID` | no example | AWS access key id | -| `CMD_S3_SECRET_ACCESS_KEY` | no example | AWS secret key | -| `CMD_S3_REGION` | `ap-northeast-1` | AWS S3 region | -| `CMD_S3_BUCKET` | no example | AWS S3 bucket name | - - -### Azure Blob Storage - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_AZURE_CONNECTION_STRING` | no example | Azure Blob Storage connection string | -| `CMD_AZURE_CONTAINER` | no example | Azure Blob Storage container name (automatically created if non existent) | - - -### imgur - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_IMGUR_CLIENTID` | no example | Imgur API client id | - - -### Minio - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_MINIO_ACCESS_KEY` | no example | Minio access key | -| `CMD_MINIO_SECRET_KEY` | no example | Minio secret key | -| `CMD_MINIO_ENDPOINT` | `minio.example.org` | Address of your Minio endpoint/instance | -| `CMD_MINIO_PORT` | `9000` | Port that is used for your Minio instance | -| `CMD_MINIO_SECURE` | `true` | If set to `true` HTTPS is used for Minio | - - -### Lutim - -| variable | example value | description | -| -------- | ------------- | ----------- | -| `CMD_LUTIM_URL` | `https://framapic.org/` | When `CMD_IMAGE_UPLOAD_TYPE` is set to `lutim`, you can setup the lutim url | - -**Note:** *Due to the rename process we renamed all `HMD_`-prefix variables to be `CMD_`-prefixed. The old ones continue to work.* - -**Note:** *relative paths are based on CodiMD's base directory* diff --git a/docs/content/configuration.md b/docs/content/configuration.md new file mode 100644 index 000000000..a73e5bbbc --- /dev/null +++ b/docs/content/configuration.md @@ -0,0 +1,445 @@ +# Configuration + +You can choose to configure HedgeDoc with either a config file or with environment variables. + +Environment variables take precedence over configurations from the config files. They generally start with `CMD_` for +our own options, but we also list node-specific options you can configure this way. + +- Environment variables are processed + in [`lib/config/environment.js`](https://github.com/hedgedoc/hedgedoc/tree/master/lib/config/environment.js) - so this + is the first place to look if anything is missing not obvious from this document. The default values are defined + in [`lib/config/default.js`](https://github.com/hedgedoc/hedgedoc/tree/master/lib/config/default.js), in case you + wonder if you even need to override it. + +- The config file is processed + in [`lib/config/index.js`](https://github.com/hedgedoc/hedgedoc/tree/master/lib/config/index.js) - so this is the + first place to look if anything is missing not obvious from this document. The default values are defined + in [`lib/config/default.js`](https://github.com/hedgedoc/hedgedoc/tree/master/lib/config/default.js), in case you + wonder if you even need to override it. To get started, it is a good idea to take the `config.json.example` and copy + it to `config.json` before filling in your own details. + +**Note:** *Due to the rename process we renamed all `HMD_`-prefix variables to be `CMD_`-prefixed. The old ones continue +to work.* + +## Node.JS + +| config file | environment | ** +default** and example value | description | | ----------- | ----------- | ----------------------------- | +-------------------------------------------------------------------------------- | | | `NODE_ENV` | `production` +or `development` | set current environment (will apply corresponding settings in the `config.json`) | | `debug` +| `DEBUG` | `true` or `false` | set debug mode, show more logs | + +## HedgeDoc basics + +| config file | environment | ** +default** and example value | description | | ------------------- | ------------------------ | +--------------------------------------------------------------------------------------------------------------------------------------------------- +| +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| | | `CMD_CONFIG_FILE` | **no default**, `/path/to/config.json` +| optional override for the path to HedgeDoc's config file | | `db` | | **`undefined`** +, `{ "dialect": "sqlite", "storage": "./db.hedgedoc.sqlite" }` +| set the db configs, [see more here](http://sequelize.readthedocs.org/en/latest/api/sequelize/) +| | `dbURL` | `CMD_DB_URL` | **`undefined`** +, `postgres://username:password@localhost:5432/hedgedoc` or `mysql://username:password@localhost:3306/hedgedoc`| Set the +db in URL style. If set, then the relevant `db` config entries will be overridden. | | `loglevel` +| `CMD_LOGLEVEL` | **`info`**, `debug` ... | Defines what kind of logs are provided to stdout. Available +options: `debug`, `verbose`, `info`, `warn`, `error` +| | `forbiddenNoteIDs` | `CMD_FORBIDDEN_NOTE_IDS` +| **`['robots.txt', 'favicon.ico', 'api', 'build', 'css', 'docs', 'fonts', 'js', 'uploads', 'vendor', 'views']`** +, `['robots.txt']` or `'robots.txt'` | disallow creation of notes, even if `allowFreeUrl` or `CMD_ALLOW_FREEURL` +is `true` +| | `imageUploadType` | `CMD_IMAGE_UPLOAD_TYPE` | **`filesystem`**, `imgur`, `s3`, `minio`, `azure`, `lutim` +| Where to upload images. For S3, see our Image Upload Guides for [S3](guides/s3-image-upload.md) +or [Minio](guides/minio-image-upload.md), also there's a whole section on their respective env vars below. | +| `sourceURL` | `CMD_SOURCE_URL` | **no default** +, `https://github.com/hedgedoc/hedgedoc/tree/` | Provides the link to the source code of +HedgeDoc on the entry page (Please, make sure you change this when you run a modified version) +| | `tooBusyLag` | `CMD_TOOBUSY_LAG` | **`70`** +| CPU time for one event loop tick until node throttles connections. (milliseconds) +| | `staticCacheTime` | | **`1 * 24 * 60 * 60 * 1000`** +| static file cache time | | `heartbeatInterval` | | **`5000`** +| socket.io heartbeat interval | | `heartbeatTimeout` | | **`10000`** +| socket.io heartbeat timeout | | `documentMaxLength` | | **`100000`** +| note max length | | `linkifyHeaderStyle` | | **`keep-case`**, `lower-case`, `gfm` +| how is a header text converted into a link id | + +## HedgeDoc paths stuff + +these are rarely used for various reasons. + +| config file | environment | ** +default** and example values | description | | ----------------- | ----------- | +----------------------------------------------------- | +------------------------------------------------------------------------------------------------ | | `defaultNotePath` | +| **`./public/default.md`** | default note file path1, empty notes will be +created with this template. | | `dhParamPath` | | **`undefined`**, `./cert/dhparam.pem` | SSL +dhparam path1 (only need when you set `useSSL`) | | `sslCAPath` | +| **`undefined`**, `['./cert/COMODORSAAddTrustCA.crt']` | SSL ca chain1 (only need when you set `useSSL`) +| | `sslCertPath` | | **`undefined`**, `./cert/hedgedoc_io.crt` | SSL cert path1 (only need +when you set `useSSL`) | | `sslKeyPath` | | **`undefined`** +, `./cert/client.key` | SSL key path1 (only need when you set `useSSL`) +| | `tmpPath` | | **`os.tmpdir()`**, `./tmp/` | temp directory path1 +| | `docsPath` | | **`./public/docs`** | docs directory path1 +| | `viewPath` | | **`./public/views`** | template directory path1 +| | `uploadsPath` | | **`./public/uploads`** | uploads directory1 - needs +to be persistent when you use imageUploadType `filesystem` | + +**Note:** *relative paths are based on HedgeDoc's base directory* + +## HedgeDoc Location + +| config file | environment | ** +default** and example value | description | | ---------------- | --------------------- | +---------------------------------------------------------------- | +----------------------------------------------------------------------------------------------------------------- | +| `domain` | `CMD_DOMAIN` | **`null`**, `localhost`, `hedgedoc.org` | domain +name | | `urlPath` | `CMD_URL_PATH` | **`null`**, `hedgedoc` | +If HedgeDoc is run from a subdirectory like `www.example.com/` | +| `host` | `CMD_HOST` | **`0.0.0.0`**, `localhost` | +interface/ip to listen on | | `port` | `CMD_PORT` | **`3000`**, `80` +| port to listen on | | `path` | `CMD_PATH` | **no default**, `/var/run/hedgedoc.sock` +| path to UNIX domain socket to listen on (if specified, `host` or `CMD_HOST` and `port` or `CMD_PORT` are ignored) | +| `protocolUseSSL` | `CMD_PROTOCOL_USESSL` | **`false`** or `true` | set to +use SSL protocol for resources path (only applied when domain is set) | | `useSSL` +| | **`false`** or `true` | set to use SSL server (if `true`, will auto turn +on `protocolUseSSL`) | | `urlAddPort` | `CMD_URL_ADDPORT` +| **`false`** or `true` | set to add port on callback URL (ports `80` +or `443` won't be applied) (only applied when domain is set) | | `allowOrigin` | `CMD_ALLOW_ORIGIN` +| **`['localhost']`**, `['hedgedoc.org']`, `['localhost', 'hedgedoc.org']` | domain name whitelist (use comma to +separate) | + +## Web security aspects + +| config file | environment | ** +default** and example value | description | | -------------- | ----------------------------- | +------------------------------------------------------------------------------------------------------------------------------------------ +| +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| | `hsts` | | `{"enable": true, "maxAgeSeconds": 31536000, "includeSubdomains": true, "preload": true}` +| [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) options to use with HTTPS (default is the example +value, max age is a year) +| | | `CMD_HSTS_ENABLE` | **`true`** or `false` +| set to enable [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) if HTTPS is also enabled (default +is ` true`) +| | | `CMD_HSTS_INCLUDE_SUBDOMAINS` | **`true`** or `false` +| set to include subdomains in HSTS (default is `true`) +| | | `CMD_HSTS_MAX_AGE` | **`31536000`**, `60 * 60 * 24 * 365` +| max duration in seconds to tell clients to keep HSTS status (default is a year) +| | | `CMD_HSTS_PRELOAD` | **`true`** or `false` +| whether to allow preloading of the site's HSTS status (e.g. into browsers) +| | `csp` | +| `{"enable": true, "directives": {"scriptSrc": "trustworthy-scripts.example.com"}, "upgradeInsecureRequests": "auto", "addDefaults": true}` +| Configures [Content Security Policy](https://helmetjs.github.io/docs/csp/). Directives are passed to Helmet - +see [their documentation](https://helmetjs.github.io/docs/csp/) for more information on the format. Some defaults are +added to the configured values so that the application doesn't break. To disable this behaviour, set `addDefaults` +to `false`. Further, if `usecdn` is on, some CDN locations are allowed too. By default (`auto`), insecure (HTTP) +requests are upgraded to HTTPS via CSP if `useSSL` is on. To change this behaviour, set `upgradeInsecureRequests` to +either `true` or `false`. | | | `CMD_CSP_ENABLE` | **`true`** or `false` +| whether to enable Content Security Policy (directives cannot be configured with environment variables) +| | | `CMD_CSP_REPORTURI` | **`undefined`**, `https://.report-uri.com/r/d/csp/enforce` +| Allows to add a URL for CSP reports in case of violations | | `cookiePolicy` | `CMD_COOKIE_POLICY` +| **`lax`**, `strict` or `none` +| Set a SameSite policy whether cookies are send from cross-origin. Be careful: setting a SameSite value of none without +https breaks the editor | + +## Privacy and External Requests + +| config file | environment | ** +default** and example value | description | | --------------- | -------------------- | ----------------------------- | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +| | `allowGravatar` | `CMD_ALLOW_GRAVATAR` | **`true`** or `false` | set to `false` to +disable [Libravatar](https://www.libravatar.org/) as profile picture source on your instance. Libravatar is a federated +open-source alternative to Gravatar. | | `useCDN` | `CMD_USECDN` | **`false`** or `true` | set to +use CDN resources or not (default is `false`) +| + +## Users and Privileges + +| config file | environment | ** +default** and example value | description | | --------------------- | --------------------------- | +----------------------------------------------------------------------- | +-------------------------------------------------------------------------------------------------------------------------------------------------------------- +| | `allowAnonymous` | `CMD_ALLOW_ANONYMOUS` | **`true`** or `false` +| Set to allow anonymous usage (default is `true`). | | `allowAnonymousEdits` | `CMD_ALLOW_ANONYMOUS_EDITS` +| **`false`** or `true` | If `allowAnonymous` is `false`: allow users +to select `freely` permission, allowing guests to edit existing notes (default is `false`). | | `allowFreeURL` +| `CMD_ALLOW_FREEURL` | **`false`** or `true` | Set to allow +new note creation by accessing a nonexistent note URL. This is the behavior familiar +from [Etherpad](https://github.com/ether/etherpad-lite). | | `defaultPermission` | `CMD_DEFAULT_PERMISSION` +| **`editable`**, `freely`, `limited`, `locked`, `protected` or `private` | Set notes default permission (only applied +on signed-in users). | | `sessionName` | | **`connect.sid`** +| Cookie session name. | | `sessionLife` | `CMD_SESSION_LIFE` | **`14 * 24 * 60 * 60 * 1000`** +, `1209600000` (14 days) | Cookie session life time in milliseconds. | | `sessionSecret` +| `CMD_SESSION_SECRET` | **`secret`** | Cookie session +secret used to sign the session cookie. If none is set, one will randomly generated on each startup, meaning all your +users will be logged out. | + +## Login methods + +### Email (local account) + +| config file | environment | ** +default** and example value | description | | -------------------- | -------------------------- | +----------------------------- | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| | `email` | `CMD_EMAIL` | **`true`** or `false` | Set to allow email sign-in. The +default is `true`. | | `allowEmailRegister` | `CMD_ALLOW_EMAIL_REGISTER` | **`true`** or `false` | Set to allow +registration of new accounts using an email address. If set to `false`, you can still create accounts using the command +line - see `bin/manage_users` for details (In production mode, remember to run it with `NODE_ENV` set as `production` in +the enviroment). This setting has no effect if `email` or `CMD_EMAIL` is `false`. The default for `allowEmailRegister` +or `CMD_ALLOW_EMAIL_REGISTER` is `true`. | + +### Dropbox Login + +| config file | environment | ** +default** and example value | description | | ----------- | -------------------------- | +------------------------------------ | +------------------------------------------------------------------------------------------------------------------------------------------- +| | `dropbox` | | `{clientID: ..., clientSecret: ...}` | An object containing the client ID and the client secret +obtained by the [Dropbox developer tools](https://www.dropbox.com/developers/apps) | | | `CMD_DROPBOX_CLIENTID` | ** +no default** | Dropbox API client id | | | `CMD_DROPBOX_CLIENTSECRET` | **no default** +| Dropbox API client secret | + +### Facebook Login + +| config file | environment | ** +default** and example value | description | | ----------- | --------------------------- | +------------------------------------ | +------------------------------------------------------------------------------------------------------------------------------------- +| | `facebook` | | `{clientID: ..., clientSecret: ...}` | An object containing the client ID and the client secret +obtained by the [Facebook app console](https://developers.facebook.com/apps) | | | `CMD_FACEBOOK_CLIENTID` | **no +default** | Facebook API client id | | | `CMD_FACEBOOK_CLIENTSECRET` | **no default** +| Facebook API client secret | + +### GitHub Login + +| config file | environment | ** +default** and example value | description | | ----------- | ------------------------- | +------------------------------------ | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| | `github` | | `{clientID: ..., clientSecret: ...}` | An object containing the client ID and the client secret +obtained by the GitHub developer page. For more details have a look at the [GitHub auth guide](guides/auth/github.md). | +| | `CMD_GITHUB_CLIENTID` | **no default** | GitHub API client id | | +| `CMD_GITHUB_CLIENTSECRET` | **no default** | GitHub API client secret | + +### GitLab Login + +| config file | environment | ** +default** and example value | description | | ----------- | ------------------------- | +---------------------------------------------------------------------------- | +----------------------------------------------------------------------------------------------------------------------------------- +| | `gitlab` | | `{baseURL: ..., scope: ..., version: ..., clientID: ..., clientSecret: ...}` | An object containing +your GitLab application data. Refer to the [GitLab guide](guides/auth/gitlab-self-hosted.md) for more details! | | +| `CMD_GITLAB_SCOPE` | **no default**, `read_user` or `api` | GitLab API +requested scope (default is `api`) (GitLab snippet import/export need `api` scope) +| | | `CMD_GITLAB_BASEURL` | **no default** | GitLab +authentication endpoint, set to use other endpoint than GitLab.com (optional) +| | | `CMD_GITLAB_CLIENTID` | **no default** | GitLab +API client id | | | `CMD_GITLAB_CLIENTSECRET` | **no default** +| GitLab API client secret | | | `CMD_GITLAB_VERSION` | **`v4`** +| GitLab API version (v3 or v4) +| + +### Google Login + +| config file | environment | ** +default** and example value | description | | ----------- | ------------------------- | +------------------------------------------------------- | +------------------------------------------------------------------------------------------------------------------------------------ +| | `google` | | `{clientID: ..., clientSecret: ..., hostedDomain: ...}` | An object containing the client ID and the +client secret obtained by the [Google API console](https://console.cloud.google.com/apis) | | | `CMD_GOOGLE_CLIENTID` +| **no default** | Google API client id | | | `CMD_GOOGLE_CLIENTSECRET` | **no +default** | Google API client secret | | | `CMD_GOOGLE_HOSTEDDOMAIN` | **no +default**, `example.com` | Provided only if the user belongs to a hosted domain. default +is `undefined` | + +### LDAP Login + +| config file | environment | ** +default** and example value | description | | ----------- | --------------------------- | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| --------------------------------------------------------------------------------------------------------------- | +| `ldap` | +| `{providerName: ..., url: ..., bindDn: ..., bindCredentials: ..., searchBase: ..., searchFilter: ..., searchAttributes: ..., usernameField: ..., useridField: ..., tlsca: ...}` +| An object detailing the LDAP connection. Refer to the [LDAP-AD guide](guides/auth/ldap-ad.md) for more details! | | +| `CMD_LDAP_URL` | **no default**, `ldap://example.com` +| URL of LDAP server | | | `CMD_LDAP_BINDDN` | **no default** +| bindDn for LDAP access | | | `CMD_LDAP_BINDCREDENTIALS` | **no default**, | bindCredentials for LDAP access | | +| `CMD_LDAP_SEARCHBASE` | **no default**, `o=users,dc=example,dc=com` +| LDAP directory to begin search from | | | `CMD_LDAP_SEARCHFILTER` | **no default**, `(uid={{username}})` +| LDAP filter to search with | | | `CMD_LDAP_SEARCHATTRIBUTES` | **no default**, `displayName, mail` +| LDAP attributes to search with (use comma to separate) | | +| `CMD_LDAP_USERIDFIELD` | **no default**, `uidNumber` or `uid` or `sAMAccountName` +| The LDAP field which is used uniquely identify a user on HedgeDoc | | | `CMD_LDAP_USERNAMEFIELD` | **no default**, +fallback to userid | The LDAP field which is used as the username on HedgeDoc | | | `CMD_LDAP_TLS_CA` | **no +default**, `server-cert.pem, root.pem` +| Root CA for LDAP TLS in PEM format (use comma to separate) | | +| `CMD_LDAP_PROVIDERNAME` | **no default**, `My institution` +| Optional name to be displayed at login form indicating the LDAP provider | + +### Mattermost Login + +| config file | environment | ** +default** and example value | description | | ------------ | ----------------------------- | +-------------------------------------------------- | +--------------------------------------------------------------------------------------------------------------------------------------------------------------- +| | `mattermost` | | `{baseURL: ..., clientID: ..., clientSecret: ...}` | An object containing the base URL of your +Mattermost application data. Refer to the [Mattermost guide](guides/auth/mattermost-self-hosted.md) for more details! | +| | `CMD_MATTERMOST_BASEURL` | **no default** | Mattermost authentication +endpoint for versions below 5.0. For Mattermost version 5.0 and above, +see [guide](guides/auth/mattermost-self-hosted.md). | | | `CMD_MATTERMOST_CLIENTID` | **no default** +| Mattermost API client id | | | `CMD_MATTERMOST_CLIENTSECRET` | **no default** | +Mattermost API client secret | + +### OAuth2 Login + +| config file | environment | ** +default** and example value | description | | ----------- | ------------------------------------------- | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| | `oauth2` | +| `{baseURL: ..., userProfileURL: ..., userProfileUsernameAttr: ..., userProfileDisplayNameAttr: ..., userProfileEmailAttr: ..., tokenURL: ..., authorizationURL: ..., clientID: ..., clientSecret: ..., scope: ...}` +| An object detailing your OAuth2 provider. Refer to the [Mattermost](guides/auth/mattermost-self-hosted.md) +or [Nextcloud](guides/auth/nextcloud.md) examples for more details! +| | | `CMD_OAUTH2_USER_PROFILE_URL` | **no default**, `https://example.com` +| Where to retrieve information about a user after successful login. Needs to output JSON. (no default value) Refer to +the [Mattermost](guides/auth/mattermost-self-hosted.md) or [Nextcloud](guides/auth/nextcloud.md) examples for more +details on all of the `CMD_OAUTH2...` options. | | | `CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR` | **no default** +, `name` +| where to find the username in the JSON from the user profile URL. (no default value) +| | | `CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR` | **no default**, `display-name` +| where to find the display-name in the JSON from the user profile URL. (no default value) +| | | `CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR` | **no default**, `email` +| where to find the email address in the JSON from the user profile URL. (no default value) +| | | `CMD_OAUTH2_USER_PROFILE_ID_ATTR` | **no default**, `user_uuid` +| where to find the dedicated user ID (optional, overrides `CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR`) +| | | `CMD_OAUTH2_TOKEN_URL` | **no default**, `https://example.com` +| sometimes called token endpoint, please refer to the documentation of your OAuth2 provider (no default value) +| | | `CMD_OAUTH2_AUTHORIZATION_URL` | **no default**, `https://example.com` +| authorization URL of your provider, please refer to the documentation of your OAuth2 provider (no default value) +| | | `CMD_OAUTH2_CLIENT_ID` | **no default**, `afae02fckafd...` +| you will get this from your OAuth2 provider when you register HedgeDoc as OAuth2-client, (no default value) +| | | `CMD_OAUTH2_CLIENT_SECRET` | **no default**, `afae02fckafd...` +| you will get this from your OAuth2 provider when you register HedgeDoc as OAuth2-client, (no default value) +| | | `CMD_OAUTH2_PROVIDERNAME` | **no default**, `My institution` +| Optional name to be displayed at login form indicating the oAuth2 provider | | | `CMD_OAUTH2_SCOPE` +| **no default**, `openid email profile` +| Scope to request for OIDC (OpenID Connect) providers. | | | `CMD_OAUTH2_ROLES_CLAIM` | **no +default**, `roles` +| ID token claim, which is supposed to provide an array of strings of roles | | | `CMD_OAUTH2_ACCESS_ROLE` +| **no default**, `role/hedgedoc` +| The role which should be included in the ID token roles claim to grant access | + +### SAML Login + +| config file | environment | ** +default** and example value | description | | ----------- | --------------------------------------- | +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| +------------------------------------------------------------------------------------------------------------------------------------------------------ +| | `saml` | +| `{idpSsoUrl: ..., idpCert: ..., clientCert: ..., issuer: ..., identifierFormat: ..., disableRequestedAuthnContext: ..., groupAttribute: ..., externalGroups: [], requiredGroups: [], attribute: {id: ..., username: ..., email: ...}}` +| An object detailing your SAML provider. Refer to the [OneLogin](guides/auth/saml-onelogin.md) +and [SAML](guides/auth/saml.md) guides for more details! | | | `CMD_SAML_IDPSSOURL` | **no default** +, `https://idp.example.com/sso` +| authentication endpoint of IdP. for details, see [guide](guides/auth/saml-onelogin.md). | | | `CMD_SAML_IDPCERT` +| **no default**, `/path/to/cert.pem` +| certificate file path of IdP in PEM format | | | `CMD_SAML_CLIENTCERT` | **no default** +, `/path/to/privatecert.pem` +| certificate file path for the client in PEM format (optional) +| | | `CMD_SAML_ISSUER` | **no default** +| Issuer to supply to identity provider (optional, default: `serverURL` config)" +| | | `CMD_SAML_DISABLEREQUESTEDAUTHNCONTEXT` | **no default**, `true` or `false` +| true to allow any authentication method, false restricts to password authentication (PasswordProtectedTransport) +method (default: false) | | | `CMD_SAML_IDENTIFIERFORMAT` +| **`urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`** +| name identifier format (optional, default: `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`) +| | | `CMD_SAML_GROUPATTRIBUTE` | **no default**, `memberOf` +| attribute name for group list (optional) +| | | `CMD_SAML_REQUIREDGROUPS` | **no default**, `hedgedoc-users` +| group names that allowed (use vertical bar to separate) (optional) +| | | `CMD_SAML_EXTERNALGROUPS` | **no default**, `Temporary-staff` +| group names that not allowed (use vertical bar to separate) (optional) +| | | `CMD_SAML_ATTRIBUTE_ID` | **no default**, `sAMAccountName` +| attribute map for `id` (optional, default: NameID of SAML response) +| | | `CMD_SAML_ATTRIBUTE_USERNAME` | **no default**, `mailNickname` +| attribute map for `username` (optional, default: NameID of SAML response) +| | | `CMD_SAML_ATTRIBUTE_EMAIL` | **no default**, `mail` +| attribute map for `email` (optional, default: NameID of SAML response if `CMD_SAML_IDENTIFIERFORMAT` is default) +| + +### Twitter Login + +| config file | environment | ** +default** and example value | description | | ----------- | ---------------------------- | +----------------------------------------- | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| | `twitter` | | `{consumerKey: ..., consumerSecret: ...}` | An object containing the consumer key and secret +obtained by the [Twitter developer tools](https://developer.twitter.com/apps). For more details have a look at +the [Twitter auth guide](guides/auth/twitter.md) | | | `CMD_TWITTER_CONSUMERKEY` | **no default** +| Twitter API consumer key | | | `CMD_TWITTER_CONSUMERSECRET` | **no default** | Twitter API +consumer secret | + +## Upload Storage + +These are only relevant when they are also configured in sync with their +`CMD_IMAGE_UPLOAD_TYPE`. Also keep in mind, that `filesystem` is available, so you don't have to use either of these. + +### Amazon S3 + +| config file | environment | ** +default** and example value | description | | ----------- | -------------------------- | +----------------------------------------------------------------------------------------------------------------- | +------------------------------------------------------------------------------------------------------------------------------------------ +| | `s3` | +| `{ "accessKeyId": "YOUR_S3_ACCESS_KEY_ID", "secretAccessKey": "YOUR_S3_ACCESS_KEY", "region": "YOUR_S3_REGION" }` | +When `imageuploadtype` be set to `s3`, you would also need to setup this key, check +our [S3 Image Upload Guide](guides/s3-image-upload.md) | | | `CMD_S3_ACCESS_KEY_ID` | **no default** +| AWS access key id | | | `CMD_S3_SECRET_ACCESS_KEY` | **no default** +| AWS secret key | | | `CMD_S3_REGION` | **no default**, `ap-northeast-1` +| AWS S3 region | | `s3bucket` | `CMD_S3_BUCKET` | **no default** +| AWS S3 bucket name | | | `CMD_S3_ENDPOINT ENV` | **no default** +| S3 API endpoint if you don't use AWS name | + +### Azure Blob Storage + +| config file | environment | ** +default** and example value | description | | ----------- | ----------------------------- | +----------------------------- | ------------------------------------------------------------------------- | | +| `CMD_AZURE_CONNECTION_STRING` | **no default** | Azure Blob Storage connection string | | +| `CMD_AZURE_CONTAINER` | **no default** | Azure Blob Storage container name (automatically +created if non existent) | + +### imgur + +| config file | environment | **default** and example value | description | +| ----------- | -------------------- | ------------------------------ | ------------------- | +| | `CMD_IMGUR_CLIENTID` | **no default** | Imgur API client id | + +### Minio + +| config file | environment | ** +default** and example value | description | | ----------- | ---------------------- | +----------------------------------------------------------------------------------------------------------------------------------------- +| +----------------------------------------------------------------------------------------------------------------------------------------------- +| | `minio` | +| `{ "accessKey": "YOUR_MINIO_ACCESS_KEY", "secretKey": "YOUR_MINIO_SECRET_KEY", "endpoint": "YOUR_MINIO_HOST", port: 9000, secure: true }` +| When `imageUploadType` is set to `minio`, you need to set this key. Also check out +our [Minio Image Upload Guide](guides/minio-image-upload.md) | | | `CMD_MINIO_ACCESS_KEY` | **no default** +| Minio access key | | | `CMD_MINIO_SECRET_KEY` | **no default** +| Minio secret key | | | `CMD_MINIO_ENDPOINT` | **no default**, `minio.example.org` +| Address of your Minio endpoint/instance | | | `CMD_MINIO_PORT` | **no default**, `9000` +| Port that is used for your Minio instance | | | `CMD_MINIO_SECURE` | **no default**, `true` +| If set to `true` HTTPS is used for Minio | + +### Lutim + +| config file | environment | ** +default** and example value | description | | ----------- | --------------- | ----------------------------- | +--------------------------------------------------------------------------- | | `lutim` | +| `{"url": "YOUR_LUTIM_URL"}` | When `imageUploadType` is set to `lutim`, you can setup the lutim url | | +| `CMD_LUTIM_URL` | **`https://framapic.org/`** | When `CMD_IMAGE_UPLOAD_TYPE` is set to `lutim`, you can setup the +lutim url | diff --git a/docs/dev/2.0.md b/docs/content/dev/2.0.md similarity index 100% rename from docs/dev/2.0.md rename to docs/content/dev/2.0.md diff --git a/docs/content/dev/api.md b/docs/content/dev/api.md new file mode 100644 index 000000000..960f53ef3 --- /dev/null +++ b/docs/content/dev/api.md @@ -0,0 +1,64 @@ +# API documentation + +Several tasks of HedgeDoc can be automated through HTTP requests. The available endpoints for this api are described in +this document. For code-autogeneration there is an OpenAPIv3-compatible description available [here](openapi.yml). + +## Notes + +These endpoints create notes, return information about them or export them. +You have to replace *\* with either the alias or id of a note you want to work on. + +| Endpoint | HTTP-Method | Description | +| ---------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `/new` | `GET` | **Creates a new +note.**
A random id will be assigned and the content will equal to the template (blank by default). After note creation a redirect is issued to the created note. | +| `/new` | `POST` | **Imports some markdown data into a new +note.**
A random id will be assigned and the content will equal to the body of the received HTTP-request. The `Content-Type: text/markdown` header should be set on this request. | +| `/new/` | `POST` | **Imports some markdown data into a new note with a + +given alias.**
This endpoint equals to the above one except that the alias from the url will be assigned to the note +if [FreeURL-mode](../configuration.md#users-and-privileges) is enabled. | | `//download` +or `/s//download` | `GET` | **Returns the raw markdown content of a note.** +| | `//publish` | `GET` | **Redirects to the published version of the note.** +| | `//slide` | `GET` | **Redirects to the slide-presentation of the +note.**
This is only useful on notes which are designed to be slides. | | `//info` +| `GET` | **Returns metadata about the note.**
This includes the title and description of the note as well as +the creation date and viewcount. The data is returned as a JSON object. | | `//revision` +| `GET` | **Returns a list of the available note revisions.**
The list is returned as a JSON object with an +array of revision-id and length associations. The revision-id equals to the timestamp when the revision was saved. | +| `//revision/` | `GET` | **Returns the revision of the note with some +metadata.**
The revision is returned as a JSON object with the content of the note and the authorship. | +| `//gist` | `GET` | **Creates a new GitHub Gist with the note's +content.**
If [GitHub integration](../configuration.md#github-login) is configured, the user will be redirected to +GitHub and a new Gist with the content of the note will be created. | + +## User / History + +These endpoints return information about the current logged-in user and it's note history. If no user is logged-in, the +most of this requests will fail with either a HTTP 403 or a JSON object containing `{"status":"forbidden"}`. + +| Endpoint | HTTP-Method | Description | +| ----------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `/me` | `GET` | **Returns the profile data of the current logged-in +user.**
The data is returned as a JSON object containing the user-id, the user's name and a url to the profile picture. | +| `/me/export` | `GET` | **Exports a zip-archive with all notes of the current +user.** | +| `/history` | `GET` | **Returns a list of the last viewed +notes.**
The list is returned as a JSON object with an array containing for each entry it's id, title, tags, last visit time and pinned status. | +| `/history` | `POST` | **Replace user's history with a new +one.**
The body must be form-encoded and contain a field `history` with a JSON-encoded array like its returned from the server when exporting the history. | +| `/history` | `DELETE` | **Deletes the user's +history.** | +| `/history/` | `POST` | **Toggles the pinned status in the history for a +note.**
The body must be form-encoded and contain a field `pinned` that is either `true` or `false`. | +| `/history/` | `DELETE` | **Deletes a note from the user's +history.** | + +## HedgeDoc-server + +These endpoints return information about the running HedgeDoc instance. + +| Endpoint | HTTP-Method | Description | +| --------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `/status` | `GET` | **Returns the current status of the HedgeDoc +instance.**
The data is returned as a JSON object containing the number of notes stored on the server, (distinct) online users and more. | diff --git a/docs/dev/db-schema.plantuml b/docs/content/dev/db-schema.plantuml similarity index 100% rename from docs/dev/db-schema.plantuml rename to docs/content/dev/db-schema.plantuml diff --git a/docs/content/dev/documentation.md b/docs/content/dev/documentation.md new file mode 100644 index 000000000..9c6ad5c56 --- /dev/null +++ b/docs/content/dev/documentation.md @@ -0,0 +1,37 @@ +# Documentation + +Our documentation is build with [mkdocs](https://www.mkdocs.org). + +## Writing + +All documentation files are found in the `docs/content` directory of +the [hedgedoc/hedgedoc repo](https://github.com/hedgedoc/hedgedoc). These files are just normal markdown files with +nothing special about them. + +The configuration for mkdocs lies in the `docs` folder in a file called `mkdocs.yml`. With that file the theme and menu + +- amoung others - can be configured. + **Please note:** Any new files need to be linked to by other files or put in the navigation or the files will be very + hard to find on the documentation website. + +## Building + +To build the documentation locally you need to perform the following steps: + +0. Make sure you have python3 installed. +1. Go into the `docs` folder. +2. Install all the dependencies (E.g. with a [venv](https://docs.python.org/3/library/venv.html)) + with `pip install -r requirements.txt` +3. Start the mkdocs dev server (`mkdocs serve`) or build the documentation (`mkdocs build`). + +## Deployment + +The documentation is deployed with [Messor Structor](https://github.com/traefik/structor). + +The necessary Dockerfile and version menu template and also the github action to build the whole documentation can be +found in the [docs.hedgedoc.org repo](https://github.com/hedgedoc/docs.hedgedoc.org). This repo is also used to deploy +the actuall website to github.io. + +Messor Structor builds and deploys the documentation by finding all branches that follow the pattern `v*`. For each +branch the docs are generated separately by first installing the dependencies from `requirements.txt` and then running +mkdocs. Afterwards the menu go template is used to include a version switcher in the theme. diff --git a/docs/dev/getting-started.md b/docs/content/dev/getting-started.md similarity index 69% rename from docs/dev/getting-started.md rename to docs/content/dev/getting-started.md index 9a35b71ab..77e3e180d 100644 --- a/docs/dev/getting-started.md +++ b/docs/content/dev/getting-started.md @@ -1,26 +1,24 @@ -Developer Notes -=== +# Getting started ## Preparing for running the code **Notice:** *There's [specialised instructions for docker](../setup/docker.md) or [heroku](../setup/heroku.md), if you prefer running code this way!* -1. Clone the repository with `git clone https://github.com/codimd/server.git codimd-server` +1. Clone the repository with `git clone https://github.com/hedgedoc/hedgedoc.git hedgedoc-server` (cloning is the preferred way, but you can also download and unzip a release) -2. Enter the directory and run `bin/setup`, which will install npm dependencies - and create configs. The setup script is written in Bash, you would need bash - as a prerequisite. -3. Setup the [config file](../configuration-config-file.md) or set up - [environment variables](../configuration-env-vars.md). +2. Enter the directory and run `bin/setup`, which will install npm dependencies and create configs. The setup script is + written in Bash, you would need bash as a prerequisite. + +3. Setup the [config file](../configuration.md) or set up + [environment variables](../configuration.md). ## Running the Code -Now that everything is in place, we can start CodiMD: - -4. `yarn run build` will build the frontend bundle. It uses webpack to do that. -5. Run the server with `node app.js` +Now that everything is in place, we can start HedgeDoc: +1. `yarn run build` will build the frontend bundle. It uses webpack to do that. +2. Run the server with `node app.js` ## Running the Code with Auto-Reload @@ -32,11 +30,10 @@ rebuild the frontend or restart the server if necessary. The commands will stay active in your terminal, so you will need multiple tabs to run both at the same time. -4. Use `yarn run dev` if you want webpack to continuously rebuild the frontend - code. -5. To auto-reload the server, the easiest method is to install [nodemon](https://www.npmjs.com/package/nodemon) - and run `nodemon --watch app.js --watch lib --watch locales app.js`. +1. Use `yarn run dev` if you want webpack to continuously rebuild the frontend code. +2. To auto-reload the server, the easiest method is to install [nodemon](https://www.npmjs.com/package/nodemon) + and run `nodemon --watch app.js --watch lib --watch locales app.js`. ## Structure @@ -44,7 +41,7 @@ The repository contains two parts: a server (backend) and a client (frontend). most of the server code is in `/lib` and most of the client code is in `public`. ```text -codimd-server/ +hedgedoc-server/ ├── docs/ --- documentation ├── lib/ --- server code ├── test/ --- test suite diff --git a/docs/content/dev/openapi.yml b/docs/content/dev/openapi.yml new file mode 100644 index 000000000..f0a180265 --- /dev/null +++ b/docs/content/dev/openapi.yml @@ -0,0 +1,456 @@ +openapi: 3.0.1 + +info: + title: HedgeDoc + description: HedgeDoc is an open source collaborative note editor. Several tasks of HedgeDoc can be automated through this API. + version: 1.7.1 + contact: + name: HedgeDoc on GitHub + url: https://github.com/hedgedoc/hedgedoc + license: + name: AGPLv3 + url: https://github.com/hedgedoc/hedgedoc/blob/master/LICENSE + +externalDocs: + url: https://github.com/hedgedoc/hedgedoc/blob/master/docs/dev/api.md + + +paths: + + /new: + get: + tags: + - note + summary: Creates a new note. + description: A random id will be assigned and the content will equal to the template (blank by default). After note creation a redirect is issued to the created note. + responses: + default: + description: Redirect to the new note + post: + tags: + - note + summary: Imports some markdown data into a new note. + description: A random id will be assigned and the content will equal to the body of the received HTTP-request. + requestBody: + required: true + description: The content of the note to be imported as markdown + content: + 'text/markdown': + example: '# Some header' + responses: + default: + description: Redirect to the imported note + + /new/{alias}: + post: + tags: + - note + summary: Imports some markdown data into a new note with a given alias. + description: 'This endpoint equals to the above one except that the alias from the url will be assigned to the note if [FreeURL-mode](../configuration-env-vars.md#users-and-privileges) is enabled.' + requestBody: + required: true + description: The content of the note to be imported as markdown + content: + 'text/markdown': + example: '# Some heading' + responses: + default: + description: Redirect to the imported note + parameters: + - name: alias + in: path + required: true + description: The alias for the note-id under which the note will be saved + content: + 'text/plain': + example: my-note + + /{note}/download: + get: + tags: + - note + summary: Returns the raw markdown content of a note. + responses: + 200: + description: The raw markdown content of the note + content: + 'text/markdown': + example: '# Some heading' + 404: + description: Note does not exist + parameters: + - name: note + in: path + required: true + description: The note which should be downloaded + content: + 'text/plain': + example: my-note + + /{note}/publish: + get: + tags: + - note + summary: Redirects to the published version of the note. + responses: + default: + description: Redirect to the published version of the note + 404: + description: Note does not exist + parameters: + - name: note + in: path + required: true + description: The note which should be published + content: + 'text/plain': + example: my-note + + /{note}/slide: + get: + tags: + - note + summary: Redirects to the slide-presentation of the note. + description: This is only useful on notes which are designed to be slides. + responses: + default: + description: Redirect to the slide version of the note + 404: + description: Note does not exist + parameters: + - name: note + in: path + required: true + description: The note which should be shown as slide + content: + 'text/plain': + example: my-note + + /{note}/info: + get: + tags: + - note + summary: Returns metadata about the note. + description: This includes the title and description of the note as well as the creation date and viewcount. + responses: + 200: + description: Metadata about the note + content: + 'text/json': + schema: + type: object + properties: + title: + type: string + description: The title of the note + default: Untitled + description: + type: string + description: The description of the note or the first words from the note + viewcount: + type: integer + minimum: 0 + description: How often the published version of the note was viewed + createtime: + type: string + description: The timestamp when the note was created in ISO 8601 format. + updatetime: + type: string + description: The timestamp when the note was last updated in ISO 8601 format. + 404: + description: Note does not exist + parameters: + - name: note + in: path + required: true + description: The note for which the info should be shown + content: + 'text/plain': + example: my-note + + /{note}/revision: + get: + tags: + - note + summary: Returns a list of the available note revisions. + description: The list is returned as a JSON object with an array of revision-id and length associations. The revision-id equals to the timestamp when the revision was saved. + responses: + 200: + description: Revisions of the note + content: + 'text/json': + schema: + type: object + properties: + revision: + type: array + description: Array that holds all revision-info objects + items: + type: object + properties: + time: + type: integer + description: UNIX-timestamp of when the revision was saved. Is also the revision-id. + length: + type: integer + description: Length of the document to the timepoint the revision was saved + 404: + description: Note does not exist + parameters: + - name: note + in: path + required: true + description: The note for which revisions should be shown + content: + 'text/plain': + example: my-note + + /{note}/revision/{revision-id}: + get: + tags: + - note + summary: Returns the revision of the note with some metadata. + description: The revision is returned as a JSON object with the content of the note and the authorship. + responses: + 200: + description: Revision of the note for the given timestamp + content: + 'text/json': + schema: + type: object + properties: + content: + type: string + description: The raw markdown content of the note revision + authorship: + type: array + description: Data which gives insights about who worked on the note + items: + type: integer + description: Unique user ids and additional data + patch: + type: array + description: Data which gives insight about what changed in comparison to former revisions + items: + type: string + 404: + description: Note does not exist + parameters: + - name: note + in: path + required: true + description: The note for which the revision should be shown + content: + 'text/plain': + example: my-note + - name: revision-id + in: path + required: true + description: The id (timestamp) of the revision to fetch + content: + 'text/plain': + example: 1570921051959 + + /{note}/gist: + get: + tags: + - note + summary: Creates a new GitHub Gist with the note's content. + description: 'If [GitHub integration](https://github.com/hedgedoc/hedgedoc/blob/master/docs/configuration-env-vars.md#github-login) is configured, the user will be redirected to GitHub and a new Gist with the content of the note will be created.' + responses: + default: + description: Redirect to the created gist (or the GitHub authentication before) + 404: + description: Note does not exist + parameters: + - name: note + in: path + required: true + description: The note which should be pasted to GitHub gist + content: + 'text/plain': + example: my-note + + /me: + get: + tags: + - user + summary: Returns the profile data of the current logged-in user. + description: The data is returned as a JSON object containing the user-id, the user's name and a url to the profile picture. Requires an active session of the user. + responses: + 200: + description: If the user is logged-in, the user data otherwise `{"status":"forbidden"}` + content: + 'text/json': + schema: + type: object + properties: + status: + type: string + description: ok if everything works as expected, forbidden is the user is not logged-in + id: + type: string + description: Unique id of the user + name: + type: string + description: The user's display name + photo: + type: string + description: An url to the online stored user profile photo + + /me/export: + get: + tags: + - user + summary: Exports a zip-archive with all notes of the current user. + responses: + default: + description: The zip-archive with all notes + + /history: + get: + tags: + - user + summary: Returns a list of the last viewed notes. + description: The list is returned as a JSON object with an array containing for each entry it's id, title, tags, last visit time and pinned status. + responses: + 200: + description: The list of recently viewed notes and pinned notes + content: + 'text/json': + schema: + type: object + properties: + history: + type: array + description: The array that contains history objects + items: + type: object + properties: + id: + type: string + description: The id or alias of the note + text: + type: string + description: The title of the note + time: + type: integer + description: The UNIX-timestamp when the note was last accessed by the user + tags: + type: array + description: The tags that were added by the user to the note + items: + type: string + pinned: + type: boolean + description: Whether the user has pinned this note + post: + tags: + - user + summary: Replace user's history with a new one. + description: The body must be form-encoded and contain a field `history` with a JSON-encoded array like its returned from the server when exporting the history. + requestBody: + required: true + content: + 'application/x-www-form-urlencoded': + example: 'history=[{"id":"example","text":"Untitled","time":1556275442010,"tags":[],"pinned":false}]' + responses: + 200: + description: History replaced + delete: + tags: + - user + summary: Deletes the user's history. + responses: + 200: + description: User's history deleted + + /history/{note}: + post: + tags: + - user + summary: Toggles the pinned status in the history for a note. + description: The body must be form-encoded and contain a field `pinned` that is either `true` or `false`. + requestBody: + required: true + content: + 'application/x-www-form-urlencoded': + example: 'pinned=false' + responses: + 200: + description: Pinned state toggled + parameters: + - name: note + in: path + required: true + description: The note for which the pinned state should be toggled + content: + 'text/plain': + example: my-note + delete: + tags: + - user + summary: Deletes a note from the user's history. + responses: + 200: + description: Pinned state toggled + parameters: + - name: note + in: path + required: true + description: The note for which the pinned state should be toggled + content: + 'text/plain': + example: my-note + + /status: + get: + tags: + - server + summary: Returns the current status of the HedgeDoc instance. + description: The data is returned as a JSON object containing the number of notes stored on the server, (distinct) online users and more. + responses: + 200: + description: The server info + content: + 'text/json': + schema: + type: object + properties: + onlineNotes: + type: integer + description: How many notes are edited at the moment + onlineUsers: + type: integer + description: How many users are online at the moment + distinctOnlineUsers: + type: integer + description: How many distinct users (different machines) are online at the moment + notesCount: + type: integer + description: How many notes are stored on the server + registeredUsers: + type: integer + description: How many users are registered on the server + onlineRegisteredUsers: + type: integer + description: How many of the online users are registered on the server + distinctOnlineRegisteredUsers: + type: integer + description: How many of the distinct online users are registered on the server + isConnectionBusy: + type: boolean + connectionSocketQueueLength: + type: integer + isDisconnectBusy: + type: boolean + disconnectSocketQueueLength: + type: integer + +tags: + - name: note + description: These endpoints create notes, return information about them or export them. + - name: user + description: These endpoints return information about the current logged-in user and it's note history. If no user is logged-in, the most of this requests will fail with either a HTTP 403 or a JSON object containing `{"status":"forbidden"}`. + - name: server + description: These endpoints return information about the running HedgeDoc instance. diff --git a/docs/dev/ot.md b/docs/content/dev/ot.md similarity index 100% rename from docs/dev/ot.md rename to docs/content/dev/ot.md diff --git a/docs/dev/public_api.yml b/docs/content/dev/public_api.yml similarity index 100% rename from docs/dev/public_api.yml rename to docs/content/dev/public_api.yml diff --git a/docs/dev/webpack.md b/docs/content/dev/webpack.md similarity index 100% rename from docs/dev/webpack.md rename to docs/content/dev/webpack.md diff --git a/docs/guides/auth/github.md b/docs/content/guides/auth/github.md similarity index 100% rename from docs/guides/auth/github.md rename to docs/content/guides/auth/github.md diff --git a/docs/guides/auth/gitlab-self-hosted.md b/docs/content/guides/auth/gitlab-self-hosted.md similarity index 100% rename from docs/guides/auth/gitlab-self-hosted.md rename to docs/content/guides/auth/gitlab-self-hosted.md diff --git a/docs/guides/auth/keycloak.md b/docs/content/guides/auth/keycloak.md similarity index 100% rename from docs/guides/auth/keycloak.md rename to docs/content/guides/auth/keycloak.md diff --git a/docs/guides/auth/ldap-AD.md b/docs/content/guides/auth/ldap-ad.md similarity index 89% rename from docs/guides/auth/ldap-AD.md rename to docs/content/guides/auth/ldap-ad.md index e74121f10..b7d0284e5 100644 --- a/docs/guides/auth/ldap-AD.md +++ b/docs/content/guides/auth/ldap-ad.md @@ -1,9 +1,8 @@ -AD LDAP auth -=== +# AD LDAP auth -To setup your CodiMD instance with Active Directory you need the following configs: +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= @@ -13,7 +12,6 @@ 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). @@ -24,7 +22,6 @@ CMD_LDAP_PROVIDERNAME=Example Inc AD `CMD_LDAP_PROVIDERNAME` just the name written above the username and password field on the login page. - Same in json: ```json @@ -38,4 +35,4 @@ Same in json: }, ``` -More details and example: https://www.npmjs.com/package/passport-ldapauth +More details and example: diff --git a/docs/guides/auth/mattermost-self-hosted.md b/docs/content/guides/auth/mattermost-self-hosted.md similarity index 100% rename from docs/guides/auth/mattermost-self-hosted.md rename to docs/content/guides/auth/mattermost-self-hosted.md diff --git a/docs/guides/auth/nextcloud.md b/docs/content/guides/auth/nextcloud.md similarity index 100% rename from docs/guides/auth/nextcloud.md rename to docs/content/guides/auth/nextcloud.md diff --git a/docs/guides/auth/oauth.md b/docs/content/guides/auth/oauth.md similarity index 100% rename from docs/guides/auth/oauth.md rename to docs/content/guides/auth/oauth.md diff --git a/docs/content/guides/auth/saml-keycloak.md b/docs/content/guides/auth/saml-keycloak.md new file mode 100644 index 000000000..2745087cd --- /dev/null +++ b/docs/content/guides/auth/saml-keycloak.md @@ -0,0 +1,143 @@ +# 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/guides/auth/saml-onelogin.md b/docs/content/guides/auth/saml-onelogin.md similarity index 100% rename from docs/guides/auth/saml-onelogin.md rename to docs/content/guides/auth/saml-onelogin.md diff --git a/docs/guides/auth/saml.md b/docs/content/guides/auth/saml.md similarity index 100% rename from docs/guides/auth/saml.md rename to docs/content/guides/auth/saml.md diff --git a/docs/guides/auth/twitter.md b/docs/content/guides/auth/twitter.md similarity index 100% rename from docs/guides/auth/twitter.md rename to docs/content/guides/auth/twitter.md diff --git a/docs/guides/migrate-etherpad.md b/docs/content/guides/migrate-etherpad.md similarity index 100% rename from docs/guides/migrate-etherpad.md rename to docs/content/guides/migrate-etherpad.md diff --git a/docs/guides/migrations-and-breaking-changes.md b/docs/content/guides/migrations-and-breaking-changes.md similarity index 100% rename from docs/guides/migrations-and-breaking-changes.md rename to docs/content/guides/migrations-and-breaking-changes.md diff --git a/docs/guides/minio-image-upload.md b/docs/content/guides/minio-image-upload.md similarity index 100% rename from docs/guides/minio-image-upload.md rename to docs/content/guides/minio-image-upload.md diff --git a/docs/guides/providing-terms.md b/docs/content/guides/providing-terms.md similarity index 100% rename from docs/guides/providing-terms.md rename to docs/content/guides/providing-terms.md diff --git a/docs/guides/s3-image-upload.md b/docs/content/guides/s3-image-upload.md similarity index 97% rename from docs/guides/s3-image-upload.md rename to docs/content/guides/s3-image-upload.md index 7ca8dd12f..626119dac 100644 --- a/docs/guides/s3-image-upload.md +++ b/docs/content/guides/s3-image-upload.md @@ -77,7 +77,7 @@ Guide - Setup CodiMD S3 image upload } ``` -9. In additional to edit `config.json` directly, you could also try [environment variables](../configuration-env-vars.md). +9. In additional to edit `config.json` directly, you could also try [environment variables](../configuration.md). ## Related Tools diff --git a/docs/history.md b/docs/content/history.md similarity index 100% rename from docs/history.md rename to docs/content/history.md diff --git a/docs/images/auth/application-page.png b/docs/content/images/auth/application-page.png similarity index 100% rename from docs/images/auth/application-page.png rename to docs/content/images/auth/application-page.png diff --git a/docs/images/auth/create-oauth-app.png b/docs/content/images/auth/create-oauth-app.png similarity index 100% rename from docs/images/auth/create-oauth-app.png rename to docs/content/images/auth/create-oauth-app.png diff --git a/docs/images/auth/create-twitter-app.png b/docs/content/images/auth/create-twitter-app.png similarity index 100% rename from docs/images/auth/create-twitter-app.png rename to docs/content/images/auth/create-twitter-app.png diff --git a/docs/images/auth/gitlab-application-details.png b/docs/content/images/auth/gitlab-application-details.png similarity index 100% rename from docs/images/auth/gitlab-application-details.png rename to docs/content/images/auth/gitlab-application-details.png diff --git a/docs/images/auth/gitlab-new-application.png b/docs/content/images/auth/gitlab-new-application.png similarity index 100% rename from docs/images/auth/gitlab-new-application.png rename to docs/content/images/auth/gitlab-new-application.png diff --git a/docs/images/auth/gitlab-sign-in.png b/docs/content/images/auth/gitlab-sign-in.png similarity index 100% rename from docs/images/auth/gitlab-sign-in.png rename to docs/content/images/auth/gitlab-sign-in.png diff --git a/docs/content/images/auth/keycloak_add_client.png b/docs/content/images/auth/keycloak_add_client.png new file mode 100644 index 000000000..79121b15a Binary files /dev/null and b/docs/content/images/auth/keycloak_add_client.png differ diff --git a/docs/content/images/auth/keycloak_client_overview.png b/docs/content/images/auth/keycloak_client_overview.png new file mode 100644 index 000000000..1ff9d9864 Binary files /dev/null and b/docs/content/images/auth/keycloak_client_overview.png differ diff --git a/docs/content/images/auth/keycloak_clients_overview.png b/docs/content/images/auth/keycloak_clients_overview.png new file mode 100644 index 000000000..388b3e002 Binary files /dev/null and b/docs/content/images/auth/keycloak_clients_overview.png differ diff --git a/docs/content/images/auth/keycloak_force_idformat.png b/docs/content/images/auth/keycloak_force_idformat.png new file mode 100644 index 000000000..1b1bf3025 Binary files /dev/null and b/docs/content/images/auth/keycloak_force_idformat.png differ diff --git a/docs/content/images/auth/keycloak_idp_cert.png b/docs/content/images/auth/keycloak_idp_cert.png new file mode 100644 index 000000000..1b899283f Binary files /dev/null and b/docs/content/images/auth/keycloak_idp_cert.png differ diff --git a/docs/content/images/auth/keycloak_mapper_email.png b/docs/content/images/auth/keycloak_mapper_email.png new file mode 100644 index 000000000..b0ad667ad Binary files /dev/null and b/docs/content/images/auth/keycloak_mapper_email.png differ diff --git a/docs/content/images/auth/keycloak_mapper_overview.png b/docs/content/images/auth/keycloak_mapper_overview.png new file mode 100644 index 000000000..8402a0bc7 Binary files /dev/null and b/docs/content/images/auth/keycloak_mapper_overview.png differ diff --git a/docs/content/images/auth/keycloak_mapper_username.png b/docs/content/images/auth/keycloak_mapper_username.png new file mode 100644 index 000000000..ccaa89549 Binary files /dev/null and b/docs/content/images/auth/keycloak_mapper_username.png differ diff --git a/docs/content/images/auth/keycloak_saml_export_cert.png b/docs/content/images/auth/keycloak_saml_export_cert.png new file mode 100644 index 000000000..e9fa5722d Binary files /dev/null and b/docs/content/images/auth/keycloak_saml_export_cert.png differ diff --git a/docs/content/images/auth/keycloak_saml_export_cert_details.png b/docs/content/images/auth/keycloak_saml_export_cert_details.png new file mode 100644 index 000000000..7f4c9e0cc Binary files /dev/null and b/docs/content/images/auth/keycloak_saml_export_cert_details.png differ diff --git a/docs/content/images/auth/keycloak_saml_import_cert.png b/docs/content/images/auth/keycloak_saml_import_cert.png new file mode 100644 index 000000000..9295edabb Binary files /dev/null and b/docs/content/images/auth/keycloak_saml_import_cert.png differ diff --git a/docs/content/images/auth/keycloak_saml_import_cert_details.png b/docs/content/images/auth/keycloak_saml_import_cert_details.png new file mode 100644 index 000000000..bb9d1d6c0 Binary files /dev/null and b/docs/content/images/auth/keycloak_saml_import_cert_details.png differ diff --git a/docs/images/auth/mattermost-enable-oauth2.png b/docs/content/images/auth/mattermost-enable-oauth2.png similarity index 100% rename from docs/images/auth/mattermost-enable-oauth2.png rename to docs/content/images/auth/mattermost-enable-oauth2.png diff --git a/docs/images/auth/mattermost-oauth-app-add.png b/docs/content/images/auth/mattermost-oauth-app-add.png similarity index 100% rename from docs/images/auth/mattermost-oauth-app-add.png rename to docs/content/images/auth/mattermost-oauth-app-add.png diff --git a/docs/images/auth/mattermost-oauth-app-done.png b/docs/content/images/auth/mattermost-oauth-app-done.png similarity index 100% rename from docs/images/auth/mattermost-oauth-app-done.png rename to docs/content/images/auth/mattermost-oauth-app-done.png diff --git a/docs/images/auth/mattermost-oauth-app-form.png b/docs/content/images/auth/mattermost-oauth-app-form.png similarity index 100% rename from docs/images/auth/mattermost-oauth-app-form.png rename to docs/content/images/auth/mattermost-oauth-app-form.png diff --git a/docs/images/auth/nextcloud-oauth2-1-settings.png b/docs/content/images/auth/nextcloud-oauth2-1-settings.png similarity index 100% rename from docs/images/auth/nextcloud-oauth2-1-settings.png rename to docs/content/images/auth/nextcloud-oauth2-1-settings.png diff --git a/docs/images/auth/nextcloud-oauth2-2-client-add.png b/docs/content/images/auth/nextcloud-oauth2-2-client-add.png similarity index 100% rename from docs/images/auth/nextcloud-oauth2-2-client-add.png rename to docs/content/images/auth/nextcloud-oauth2-2-client-add.png diff --git a/docs/images/auth/nextcloud-oauth2-3-clientid-secret.png b/docs/content/images/auth/nextcloud-oauth2-3-clientid-secret.png similarity index 100% rename from docs/images/auth/nextcloud-oauth2-3-clientid-secret.png rename to docs/content/images/auth/nextcloud-oauth2-3-clientid-secret.png diff --git a/docs/images/auth/onelogin-add-app.png b/docs/content/images/auth/onelogin-add-app.png similarity index 100% rename from docs/images/auth/onelogin-add-app.png rename to docs/content/images/auth/onelogin-add-app.png diff --git a/docs/images/auth/onelogin-copy-idp-metadata.png b/docs/content/images/auth/onelogin-copy-idp-metadata.png similarity index 100% rename from docs/images/auth/onelogin-copy-idp-metadata.png rename to docs/content/images/auth/onelogin-copy-idp-metadata.png diff --git a/docs/images/auth/onelogin-edit-app-name.png b/docs/content/images/auth/onelogin-edit-app-name.png similarity index 100% rename from docs/images/auth/onelogin-edit-app-name.png rename to docs/content/images/auth/onelogin-edit-app-name.png diff --git a/docs/images/auth/onelogin-edit-sp-metadata.png b/docs/content/images/auth/onelogin-edit-sp-metadata.png similarity index 100% rename from docs/images/auth/onelogin-edit-sp-metadata.png rename to docs/content/images/auth/onelogin-edit-sp-metadata.png diff --git a/docs/images/auth/onelogin-select-template.png b/docs/content/images/auth/onelogin-select-template.png similarity index 100% rename from docs/images/auth/onelogin-select-template.png rename to docs/content/images/auth/onelogin-select-template.png diff --git a/docs/images/auth/onelogin-use-dashboard.png b/docs/content/images/auth/onelogin-use-dashboard.png similarity index 100% rename from docs/images/auth/onelogin-use-dashboard.png rename to docs/content/images/auth/onelogin-use-dashboard.png diff --git a/docs/images/auth/register-oauth-application-form.png b/docs/content/images/auth/register-oauth-application-form.png similarity index 100% rename from docs/images/auth/register-oauth-application-form.png rename to docs/content/images/auth/register-oauth-application-form.png diff --git a/docs/images/auth/register-twitter-application.png b/docs/content/images/auth/register-twitter-application.png similarity index 100% rename from docs/images/auth/register-twitter-application.png rename to docs/content/images/auth/register-twitter-application.png diff --git a/docs/images/auth/twitter-app-confirmation.png b/docs/content/images/auth/twitter-app-confirmation.png similarity index 100% rename from docs/images/auth/twitter-app-confirmation.png rename to docs/content/images/auth/twitter-app-confirmation.png diff --git a/docs/images/auth/twitter-app-keys.png b/docs/content/images/auth/twitter-app-keys.png similarity index 100% rename from docs/images/auth/twitter-app-keys.png rename to docs/content/images/auth/twitter-app-keys.png diff --git a/docs/content/images/favicon.png b/docs/content/images/favicon.png new file mode 100644 index 000000000..80afec65c Binary files /dev/null and b/docs/content/images/favicon.png differ diff --git a/docs/content/images/hedgedoc_logo_horizontal.svg b/docs/content/images/hedgedoc_logo_horizontal.svg new file mode 100644 index 000000000..e6dc0aa5d --- /dev/null +++ b/docs/content/images/hedgedoc_logo_horizontal.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + diff --git a/docs/content/images/logo.svg b/docs/content/images/logo.svg new file mode 100644 index 000000000..c194df468 --- /dev/null +++ b/docs/content/images/logo.svg @@ -0,0 +1,14 @@ + + + + + diff --git a/docs/images/minio-image-upload/create-bucket.png b/docs/content/images/minio-image-upload/create-bucket.png similarity index 100% rename from docs/images/minio-image-upload/create-bucket.png rename to docs/content/images/minio-image-upload/create-bucket.png diff --git a/docs/images/minio-image-upload/create-policy.png b/docs/content/images/minio-image-upload/create-policy.png similarity index 100% rename from docs/images/minio-image-upload/create-policy.png rename to docs/content/images/minio-image-upload/create-policy.png diff --git a/docs/images/minio-image-upload/default-view.png b/docs/content/images/minio-image-upload/default-view.png similarity index 100% rename from docs/images/minio-image-upload/default-view.png rename to docs/content/images/minio-image-upload/default-view.png diff --git a/docs/images/minio-image-upload/docker-logs.png b/docs/content/images/minio-image-upload/docker-logs.png similarity index 100% rename from docs/images/minio-image-upload/docker-logs.png rename to docs/content/images/minio-image-upload/docker-logs.png diff --git a/docs/images/minio-image-upload/open-edit-policy.png b/docs/content/images/minio-image-upload/open-edit-policy.png similarity index 100% rename from docs/images/minio-image-upload/open-edit-policy.png rename to docs/content/images/minio-image-upload/open-edit-policy.png diff --git a/docs/images/s3-image-upload/bucket-policy-editor.png b/docs/content/images/s3-image-upload/bucket-policy-editor.png similarity index 100% rename from docs/images/s3-image-upload/bucket-policy-editor.png rename to docs/content/images/s3-image-upload/bucket-policy-editor.png diff --git a/docs/images/s3-image-upload/bucket-property.png b/docs/content/images/s3-image-upload/bucket-property.png similarity index 100% rename from docs/images/s3-image-upload/bucket-property.png rename to docs/content/images/s3-image-upload/bucket-property.png diff --git a/docs/images/s3-image-upload/create-bucket.png b/docs/content/images/s3-image-upload/create-bucket.png similarity index 100% rename from docs/images/s3-image-upload/create-bucket.png rename to docs/content/images/s3-image-upload/create-bucket.png diff --git a/docs/images/s3-image-upload/custom-policy.png b/docs/content/images/s3-image-upload/custom-policy.png similarity index 100% rename from docs/images/s3-image-upload/custom-policy.png rename to docs/content/images/s3-image-upload/custom-policy.png diff --git a/docs/images/s3-image-upload/iam-user.png b/docs/content/images/s3-image-upload/iam-user.png similarity index 100% rename from docs/images/s3-image-upload/iam-user.png rename to docs/content/images/s3-image-upload/iam-user.png diff --git a/docs/images/s3-image-upload/review-policy.png b/docs/content/images/s3-image-upload/review-policy.png similarity index 100% rename from docs/images/s3-image-upload/review-policy.png rename to docs/content/images/s3-image-upload/review-policy.png diff --git a/docs/content/index.md b/docs/content/index.md new file mode 100644 index 000000000..50ef5bc16 --- /dev/null +++ b/docs/content/index.md @@ -0,0 +1,25 @@ +# Welcome to the HedgeDoc Documentation + +![HedgeDoc Logo](images/hedgedoc_logo_horizontal.svg) + +HedgeDoc lets you create real-time collaborative markdown notes. You can test-drive it by visiting +our [HedgeDoc demo server][hedgedoc-demo]. + +It is inspired by Hackpad, Etherpad and similar collaborative editors. This project originated with the team +at [HackMD](https://hackmd.io) and now forked into its own +organisation. [A longer writeup can be read in the history doc](history.md) +or [you can have a look at an explanitory graph over at our website][hedgedoc-history]. + +If you have any questions that aren't answered here, feel free to ask us on [Matrix][matrix.org-url], stop by +our [community forums][hedgedoc-community] or have a look at our [FAQ][hedgedoc-faq]. + + +[hedgedoc-demo]: https://demo.hedgedoc.org + +[hedgedoc-history]: https://hedgedoc.org/history + +[hedgedoc-faq]: https://hedgedoc.org/faq + +[matrix.org-url]: https://chat.hedgedoc.org + +[hedgedoc-community]: https://community.hedgedoc.org diff --git a/docs/legal/developer-certificate-of-origin.txt b/docs/content/legal/developer-certificate-of-origin.txt similarity index 100% rename from docs/legal/developer-certificate-of-origin.txt rename to docs/content/legal/developer-certificate-of-origin.txt diff --git a/docs/setup/cloudron.md b/docs/content/setup/cloudron.md similarity index 100% rename from docs/setup/cloudron.md rename to docs/content/setup/cloudron.md diff --git a/docs/content/setup/docker-linuxserver.md b/docs/content/setup/docker-linuxserver.md new file mode 100644 index 000000000..cfdf8fd6c --- /dev/null +++ b/docs/content/setup/docker-linuxserver.md @@ -0,0 +1,26 @@ +# LinuxServer.io HedgeDoc Image + +[![Discord](https://img.shields.io/discord/354974912613449730.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=Discord&logo=discord)](https://discord.gg/YWrKVTn "realtime support / chat with the community and the team.") +[![GitHub Release](https://img.shields.io/github/release/linuxserver/docker-hedgedoc.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=github)](https://github.com/linuxserver/docker-hedgedoc/releases) +[![GitHub Package Repository](https://img.shields.io/static/v1.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=linuxserver.io&message=GitHub%20Package&logo=github)](https://github.com/linuxserver/docker-hedgedoc/packages) +[![GitLab Container Registry](https://img.shields.io/static/v1.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=linuxserver.io&message=GitLab%20Registry&logo=gitlab)](https://gitlab.com/linuxserver.io/docker-hedgedoc/container_registry) +[![MicroBadger Layers](https://img.shields.io/microbadger/layers/linuxserver/hedgedoc.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge)](https://microbadger.com/images/linuxserver/hedgedoc "Get your own version badge on microbadger.com") +[![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/hedgedoc.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=pulls&logo=docker)](https://hub.docker.com/r/linuxserver/hedgedoc) +[![Docker Stars](https://img.shields.io/docker/stars/linuxserver/hedgedoc.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=stars&logo=docker)](https://hub.docker.com/r/linuxserver/hedgedoc) +[![Jenkins Build](https://img.shields.io/jenkins/build?labelColor=555555&logoColor=ffffff&style=for-the-badge&jobUrl=https%3A%2F%2Fci.linuxserver.io%2Fjob%2FDocker-Pipeline-Builders%2Fjob%2Fdocker-hedgedoc%2Fjob%2Fmain%2F&logo=jenkins)](https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-hedgedoc/job/main/) +[![LSIO CI](https://img.shields.io/badge/dynamic/yaml?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=CI&query=CI&url=https%3A%2F%2Fci-tests.linuxserver.io%2Flinuxserver%2Fhedgedoc%2Flatest%2Fci-status.yml)](https://ci-tests.linuxserver.io/linuxserver/hedgedoc/latest/index.html) + +[LinuxServer.io](https://linuxserver.io) have created an Ubuntu-based multi-arch container image for x86-64, arm64 and +armhf. + +- It supports all the environment variables detailed in the [configuration documentation](../configuration.md) to modify + it according to your needs. +- It gets rebuilt on new releases from HedgeDoc and also weekly if necessary to update any other package changes in the + underlying container, making it easy to keep your HedgeDoc instance up to date. +- It also details how to + easily [utilize Docker networking to reverse proxy](https://github.com/linuxserver/docker-hedgedoc/#application-setup) + HedgeDoc using their [SWAG docker image](https://github.com/linuxserver/docker-swag) + +In order to contribute check the LinuxServer.io [GitHub repository](https://github.com/linuxserver/docker-hedgedoc/) for +HedgeDoc. And to find all tags and versions of the image, check +the [Docker Hub repository](https://hub.docker.com/r/linuxserver/hedgedoc). diff --git a/docs/setup/docker.md b/docs/content/setup/docker.md similarity index 100% rename from docs/setup/docker.md rename to docs/content/setup/docker.md diff --git a/docs/setup/heroku.md b/docs/content/setup/heroku.md similarity index 100% rename from docs/setup/heroku.md rename to docs/content/setup/heroku.md diff --git a/docs/setup/kubernetes.md b/docs/content/setup/kubernetes.md similarity index 100% rename from docs/setup/kubernetes.md rename to docs/content/setup/kubernetes.md diff --git a/docs/setup/manual-setup.md b/docs/content/setup/manual-setup.md similarity index 100% rename from docs/setup/manual-setup.md rename to docs/content/setup/manual-setup.md diff --git a/docs/content/setup/reverse-proxy.md b/docs/content/setup/reverse-proxy.md new file mode 100644 index 000000000..8420a281b --- /dev/null +++ b/docs/content/setup/reverse-proxy.md @@ -0,0 +1,96 @@ +# Using a Reverse Proxy with HedgeDoc + +If you want to use a reverse proxy to serve HedgeDoc, here are the essential configs that you'll have to do. + +This documentation will cover HTTPS setup, with comments for HTTP setup. + +## HedgeDoc config + +[Full explanation of the configuration options](../configuration.md) + +| `config.json` parameter | Environment variable | Value | Example | +|-------------------------|----------------------|-------|---------| +| `domain` | `CMD_DOMAIN` | The full domain where your instance will be available | `hedgedoc.example.com` | +| `host` | `CMD_HOST` | An ip or domain name that is only available to HedgeDoc and your reverse proxy | `localhost` | +| `port` | `CMD_PORT` | An available port number on that IP | `3000` | +| `path` | `CMD_PATH` | path to UNIX domain socket to listen on (if specified, `host` or `CMD_HOST` and `port` or `CMD_PORT` are ignored) | `/var/run/hedgedoc.sock` | +| `protocolUseSSL` | `CMD_PROTOCOL_USESSL` | `true` if you want to serve your instance over SSL (HTTPS), `false` if you want to use plain HTTP | `true` | +| `useSSL` | | `false`, the communications between HedgeDoc and the proxy are unencrypted | `false` | +| `urlAddPort` | `CMD_URL_ADDPORT` | `false`, HedgeDoc should not append its port to the URLs it links | `false` | +| `hsts.enable` | `CMD_HSTS_ENABLE` | `true` if you host over SSL, `false` otherwise | `true` | + +## Reverse Proxy config + +### Generic + +The reverse proxy must allow websocket `Upgrade` requests at path `/sockets.io/`. + +It must pass through the scheme used by the client (http or https). + +### Nginx + +Here is an example configuration for Nginx. + +``` +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} +server { + server_name hedgedoc.example.com; + + location / { + proxy_pass http://127.0.0.1:3000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /socket.io/ { + proxy_pass http://127.0.0.1:3000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + } + + listen [::]:443 ssl http2; + listen 443 ssl http2; + ssl_certificate fullchain.pem; + ssl_certificate_key privkey.pem; + include options-ssl-nginx.conf; + ssl_dhparam ssl-dhparams.pem; +} +``` + +### Apache + +You will need these modules enabled: `proxy`, `proxy_http` and `proxy_wstunnel`. +Here is an example config snippet: + +``` + + ServerName hedgedoc.example.com + + RewriteEngine on + RewriteCond %{REQUEST_URI} ^/socket.io [NC] + RewriteCond %{HTTP:Upgrade} =websocket [NC] + RewriteRule /(.*) ws://127.0.0.1:3000/$1 [P,L] + + ProxyPass / http://127.0.0.1:3000/ + ProxyPassReverse / http://127.0.0.1:3000/ + + RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME} + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + SSLCertificateFile /etc/letsencrypt/live/hedgedoc.example.com/fullchain.pem + SSLCertificateKeyFile /etc/letsencrypt/live/hedgedoc.example.com/privkey.pem + Include /etc/letsencrypt/options-ssl-apache.conf + +``` + diff --git a/docs/content/setup/yunohost.md b/docs/content/setup/yunohost.md new file mode 100644 index 000000000..05f0073e0 --- /dev/null +++ b/docs/content/setup/yunohost.md @@ -0,0 +1,9 @@ +YunoHost +=== + +HedgeDoc is available as a 1-click install on [YunoHost](https://yunohost.org/). YunoHost is a Debian GNU/Linux based +distribution packaged with free software that automates the installation of a personal web server. + +[![Install HedgeDoc with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=hedgedoc) + +The source code for the package can be found [here](https://github.com/YunoHost-Apps/hedgedoc_ynh). diff --git a/docs/slide-options.md b/docs/content/slide-options.md similarity index 100% rename from docs/slide-options.md rename to docs/content/slide-options.md diff --git a/docs/content/theme/styles/hedgedoc-color.css b/docs/content/theme/styles/hedgedoc-color.css new file mode 100644 index 000000000..319bf8302 --- /dev/null +++ b/docs/content/theme/styles/hedgedoc-color.css @@ -0,0 +1,14 @@ +[data-md-color-primary=hedgedoc] { + --md-primary-fg-color: #b51f08; + --md-primary-fg-color--light: #b51f08; + --md-primary-fg-color--dark: #b51f08; + --md-primary-bg-color: hsla(0, 0%, 100%, 1); + --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7); +} + +[data-md-color-accent=hedgedoc] { + --md-accent-fg-color: #b51f08; + --md-accent-fg-color--transparent: hsla(348, 100%, 55%, 0.1); + --md-accent-bg-color: hsla(0, 0%, 100%, 1); + --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7); +} diff --git a/docs/content/url-scheme.md b/docs/content/url-scheme.md new file mode 100644 index 000000000..c8b0ee7db --- /dev/null +++ b/docs/content/url-scheme.md @@ -0,0 +1,39 @@ +# URL scheme + +HedgeDoc has three different modes for viewing a stored note. Each mode has a slightly different URL for accessing it. +This document gives an overview about these URLs. +We assume that you replace `pad.example.com` with the domain of your instance. + +## Default (random) + +When you create a new note by clicking the "New note" button, your note is given a long random id and a random short-id. +The long id is needed for accessing the editor and the live-update view. The short-id is used for the "published" +version of a note that is read-only and does not update in realtime as well as for the presentation mode. + +| example URL | prefix | mode | content updates | +| -------------------------------------- | ------ | ----------------- | --------------- | +| pad.example.com/Ndmv3oCyREKZMjSGR9uhnQ | *none* | editor | in realtime | +| pad.example.com/s/ByXF7k-YI | s/ | read-only version | on reload | +| pad.example.com/p/ByXF7k-YI | p/ | presentation mode | on reload | + +## FreeURL mode + +If the setting `CMD_ALLOW_FREEURL` is enabled, users may create notes with a custom alias URL by just visiting the +editor version of a custom alias. The published version and the presentation mode may also be accessed with the custom +alias. + +| example URL | prefix | mode | content updates | +| --------------------------------- | ------ | ----------------- | --------------- | +| pad.example.com/my-awesome-note | *none* | editor | in realtime | +| pad.example.com/s/my-awesome-note | s/ | read-only version | on reload | +| pad.example.com/p/my-awesome-note | p/ | presentation mode | on reload | + +## Different editor modes + +The editor has three different sub-modes. All of these update the content in realtime. + +| example URL | icon in the navbar | behaviour | +| ------------------------------- | -------------------| ----------------------------------------------- | +| pad.example.com/longnoteid?edit | pencil | Full-screen markdown editor for the content | +| pad.example.com/longnoteid?view | eye | Full-screen view of the note without the editor | +| pad.example.com/longnoteid?both | columns | markdown editor and view mode side-by-side | diff --git a/docs/dev/api.md b/docs/dev/api.md deleted file mode 100644 index c27e1d4a6..000000000 --- a/docs/dev/api.md +++ /dev/null @@ -1,42 +0,0 @@ -# API documentation -Several tasks of CodiMD can be automated through HTTP requests. -The available endpoints for this api are described in this document. -For code-autogeneration there is an OpenAPIv3-compatible description available [here](openapi.yml). - -## Notes -These endpoints create notes, return information about them or export them. -You have to replace _\_ with either the alias or id of a note you want to work on. - -| Endpoint | HTTP-Method | Description | -|---|---|---| -| `/new` | `GET` | **Creates a new note.**
A random id will be assigned and the content will equal to the template (blank by default). After note creation a redirect is issued to the created note. | -| `/new` | `POST` | **Imports some markdown data into a new note.**
A random id will be assigned and the content will equal to the body of the received HTTP-request. The `Content-Type: text/markdown` header should be set on this request. | -| `/new/` | `POST` | **Imports some markdown data into a new note with a given alias.**
This endpoint equals to the above one except that the alias from the url will be assigned to the note if [FreeURL-mode](../configuration-env-vars.md#users-and-privileges) is enabled. | -| `//download` or `/s//download` | `GET` | **Returns the raw markdown content of a note.** | -| `//publish` | `GET` | **Redirects to the published version of the note.** | -| `//slide` | `GET` | **Redirects to the slide-presentation of the note.**
This is only useful on notes which are designed to be slides. | -| `//info` | `GET` | **Returns metadata about the note.**
This includes the title and description of the note as well as the creation date and viewcount. The data is returned as a JSON object. | -| `//revision` | `GET` | **Returns a list of the available note revisions.**
The list is returned as a JSON object with an array of revision-id and length associations. The revision-id equals to the timestamp when the revision was saved. | -| `//revision/` | `GET` | **Returns the revision of the note with some metadata.**
The revision is returned as a JSON object with the content of the note and the authorship. | -| `//gist` | `GET` | **Creates a new GitHub Gist with the note's content.**
If [GitHub integration](../configuration-env-vars.md#github-login) is configured, the user will be redirected to GitHub and a new Gist with the content of the note will be created. | - -## User / History -These endpoints return information about the current logged-in user and it's note history. If no user is logged-in, the most of this requests will fail with either a HTTP 403 or a JSON object containing `{"status":"forbidden"}`. - -| Endpoint | HTTP-Method | Description | -|---|---|---| -| `/me` | `GET` | **Returns the profile data of the current logged-in user.**
The data is returned as a JSON object containing the user-id, the user's name and a url to the profile picture. | -| `/me/export` | `GET` | **Exports a zip-archive with all notes of the current user.** | -| `/history` | `GET` | **Returns a list of the last viewed notes.**
The list is returned as a JSON object with an array containing for each entry it's id, title, tags, last visit time and pinned status. | -| `/history` | `POST` | **Replace user's history with a new one.**
The body must be form-encoded and contain a field `history` with a JSON-encoded array like its returned from the server when exporting the history. | -| `/history` | `DELETE` | **Deletes the user's history.** | -| `/history/` | `POST` | **Toggles the pinned status in the history for a note.**
The body must be form-encoded and contain a field `pinned` that is either `true` or `false`. -| `/history/` | `DELETE` | **Deletes a note from the user's history.** | - - -## CodiMD-server -These endpoints return information about the running CodiMD instance. - -| Endpoint | HTTP-Method | Description | -|---|---|---| -| `/status` | `GET` | **Returns the current status of the CodiMD instance.**
The data is returned as a JSON object containing the number of notes stored on the server, (distinct) online users and more. | diff --git a/docs/images/CodiMD-1.3.2-features.png b/docs/images/CodiMD-1.3.2-features.png deleted file mode 100644 index 952efe304..000000000 Binary files a/docs/images/CodiMD-1.3.2-features.png and /dev/null differ diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 000000000..d563115c5 --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,61 @@ +site_name: HedgeDoc +site_url: https://docs.hedgedoc.org +repo_url: https://github.com/hedgedoc/hedgedoc +site_description: 'HedgeDoc Documentation' +site_author: 'HedgeDoc Developers' +docs_dir: content +nav: + - Home: index.md + - Installation: + - 'Manual Installation': setup/manual-setup.md + - 'Reverse Proxy': setup/reverse-proxy.md + - Docker: setup/docker.md + - Cloudron: setup/cloudron.md + - Heroku: setup/heroku.md + - LinuxServer: setup/docker-linuxserver.md + - Yunohost: setup/yunohost.md + - Guides: + - Authentication: + - LDAP: guides/auth/ldap-ad.md + - OAuth: guides/auth/oauth.md + - SAML: guides/auth/saml.md + - SAML Keycloak: guides/auth/saml-keycloak.md + - SAML Onelogin: guides/auth/saml-onelogin.md + - GitHub: guides/auth/github.md + - GitLab: guides/auth/gitlab-self-hosted.md + - Keycloak: guides/auth/keycloak.md + - NextCloud: guides/auth/nextcloud.md + - Twitter: guides/auth/twitter.md + - Migrate from Etherpad: guides/migrate-etherpad.md + - Breaking Changes: guides/migrations-and-breaking-changes.md + - Media Backend: + - Minion: guides/minio-image-upload.md + - S3: guides/s3-image-upload.md + - Setting Terms: guides/providing-terms.md + - Configuration: configuration.md + - Developer: + - 'Getting Started': dev/getting-started.md + - API: dev/api.md + - 'Operational Transformation': dev/ot.md + - Webpack: dev/webpack.md + - 'Documentation': dev/documentation.md + - FAQ: https://hedgedoc.org/faq +markdown_extensions: + - toc: + permalink: true +theme: + name: 'material' + language: en + favicon: images/favicon.png + logo: images/logo.svg + palette: + scheme: light + primary: 'hedgedoc' + accent: 'hedgedoc' + features: + - navigation.tabs + - navigation.sections + - toc.integrate + +extra_css: + - theme/styles/hedgedoc-color.css diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 000000000..57d08e48d --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,3 @@ +mkdocs==1.1.2 +mkdocs-material==6.2.3 +pymdown-extensions==8.1 diff --git a/docs/setup/docker-linuxserver.md b/docs/setup/docker-linuxserver.md deleted file mode 100644 index 2b6c09738..000000000 --- a/docs/setup/docker-linuxserver.md +++ /dev/null @@ -1,14 +0,0 @@ -LinuxServer.io CodiMD Image -=== -[![LinuxServer.io Discord](https://img.shields.io/discord/354974912613449730.svg?logo=discord&label=LSIO%20Discord&style=flat-square)](https://discord.gg/YWrKVTn)[![container version badge](https://images.microbadger.com/badges/version/linuxserver/codimd.svg)](https://microbadger.com/images/linuxserver/codimd "Get your own version badge on microbadger.com")[![container image size badge](https://images.microbadger.com/badges/image/linuxserver/codimd.svg)](https://microbadger.com/images/linuxserver/codimd "Get your own version badge on microbadger.com")![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/codimd.svg)![Docker Stars](https://img.shields.io/docker/stars/linuxserver/codimd.svg)[![Build Status](https://ci.linuxserver.io/buildStatus/icon?job=Docker-Pipeline-Builders/docker-codimd/master)](https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-codimd/job/master/)[![LinuxServer.io CI summary](https://lsio-ci.ams3.digitaloceanspaces.com/linuxserver/codimd/latest/badge.svg)](https://lsio-ci.ams3.digitaloceanspaces.com/linuxserver/codimd/latest/index.html) - -[LinuxServer.io](https://linuxserver.io) have created an Ubuntu-based multi-arch container image for x86-64, arm64 and armhf. - -- It supports all the environment variables detailed in the [configuration documentation](../configuration-env-vars.md) to modify it according to your needs. - -- It gets rebuilt on new releases from CodiMD and also weekly if necessary to update any other package changes in the underlying container, making it easy to keep your CodiMD instance up to date. - -- It also details how to easily [utilize Docker networking to reverse proxy](https://github.com/linuxserver/docker-codimd/#application-setup) CodiMD using their [LetsEncrypt docker image](https://github.com/linuxserver/docker-letsencrypt) - -In order to contribute check the LinuxServer.io [GitHub repository](https://github.com/linuxserver/docker-codimd/) for CodiMD. -And to find all tags and versions of the image, check the [Docker Hub repository](https://hub.docker.com/r/linuxserver/codimd).