Merge pull request #660 from hedgedoc/cherry-picks-from-master

Cherry-Picks from master & cleanups
This commit is contained in:
David Mehren 2021-01-05 21:47:31 +01:00 committed by GitHub
commit 2701a12092
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
231 changed files with 1510 additions and 12719 deletions

View file

@ -1,6 +0,0 @@
old_src/lib/ot
old_src/lib/migrations
public/vendor
public/build
node_modules
build

View file

@ -2,7 +2,7 @@
name: Bug report
about: Create a report to help us improve HedgeDoc.
title: ''
labels: 'bug'
labels: 'type: bug'
assignees: ''
---

View file

@ -2,7 +2,7 @@
name: Enhancement request
about: Suggest an enhancement of an existing feature.
title: ''
labels: 'enhancement'
labels: 'type: enhancement'
assignees: ''
---

View file

@ -2,7 +2,7 @@
name: Feature request
about: Suggest a new feature for this project, which isn't existing yet.
title: ''
labels: 'feature request'
labels: 'type: feature'
assignees: ''
---

View file

@ -2,7 +2,7 @@
name: Question / Other
about: Questions about the project, features, or organziational issues
title: ''
labels: question
labels: 'type: question'
assignees: ''
---

View file

@ -6,12 +6,13 @@ This PR fixes/adds/improves/...
### Steps
<!-- please tick steps this PR performs (if something is not necessary, please tick anyway to indicate you considered it) -->
<!-- Please tick all steps this PR performs (if something is not necessary, please remove it) -->
- [ ] added implementation
- [ ] added / updated tests
- [ ] added / updated documentation
- [ ] extended changelog
- [ ] Added implementation
- [ ] Added / updated tests
- [ ] Added / updated documentation
- [ ] I read the [contribution documentation](https://github.com/hedgedoc/hedgedoc/blob/develop/CONTRIBUTING.md) and
signed-off my commits to accept the DCO.
### Related Issue(s)
<!-- e.g #123 -->

View file

@ -1,27 +0,0 @@
language: node_js
dist: xenial
cache: yarn
stages:
- Static Tests
- test
node_js:
- 10
- 12
- 14
env:
- TEST_SUITE=test
- TEST_SUITE=test:e2e
script: "yarn run $TEST_SUITE"
jobs:
include:
- stage: Static Tests
name: eslint
script:
- yarn run lint
- name: ShellCheck
script:
- shellcheck bin/heroku bin/setup
language: generic

View file

@ -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

135
app.json
View file

@ -1,135 +0,0 @@
{
"name": "CodiMD",
"description": "Realtime collaborative markdown notes on all platforms",
"keywords": [
"Collaborative",
"Markdown",
"Notes"
],
"website": "https://codimd.org",
"repository": "https://github.com/codimd/server",
"logo": "https://github.com/codimd/server/raw/master/public/codimd-icon-1024.png",
"success_url": "/",
"env": {
"NPM_CONFIG_PRODUCTION": {
"description": "Let npm also install development build tool",
"value": "false"
},
"DB_TYPE": {
"description": "Specify database type. See sequelize available databases. Default using postgres",
"value": "postgres"
},
"CMD_SESSION_SECRET": {
"description": "Secret used to secure session cookies.",
"required": false
},
"CMD_HSTS_ENABLE": {
"description": "whether to also use HSTS if HTTPS is enabled",
"required": false
},
"CMD_HSTS_MAX_AGE": {
"description": "max duration, in seconds, to tell clients to keep HSTS status",
"required": false
},
"CMD_HSTS_INCLUDE_SUBDOMAINS": {
"description": "whether to tell clients to also regard subdomains as HSTS hosts",
"required": false
},
"CMD_HSTS_PRELOAD": {
"description": "whether to allow at all adding of the site to HSTS preloads (e.g. in browsers)",
"required": false
},
"CMD_DOMAIN": {
"description": "domain name",
"required": false
},
"CMD_URL_PATH": {
"description": "sub url path, like `www.example.com/<URL_PATH>`",
"required": false
},
"CMD_ALLOW_ORIGIN": {
"description": "domain name whitelist (use comma to separate)",
"required": false,
"value": "localhost"
},
"CMD_PROTOCOL_USESSL": {
"description": "set to use ssl protocol for resources path (only applied when domain is set)",
"required": false
},
"CMD_URL_ADDPORT": {
"description": "set to add port on callback url (port 80 or 443 won't applied) (only applied when domain is set)",
"required": false
},
"CMD_FACEBOOK_CLIENTID": {
"description": "Facebook API client id",
"required": false
},
"CMD_FACEBOOK_CLIENTSECRET": {
"description": "Facebook API client secret",
"required": false
},
"CMD_TWITTER_CONSUMERKEY": {
"description": "Twitter API consumer key",
"required": false
},
"CMD_TWITTER_CONSUMERSECRET": {
"description": "Twitter API consumer secret",
"required": false
},
"CMD_GITHUB_CLIENTID": {
"description": "GitHub API client id",
"required": false
},
"CMD_GITHUB_CLIENTSECRET": {
"description": "GitHub API client secret",
"required": false
},
"CMD_GITLAB_BASEURL": {
"description": "GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional)",
"required": false
},
"CMD_GITLAB_CLIENTID": {
"description": "GitLab API client id",
"required": false
},
"CMD_GITLAB_CLIENTSECRET": {
"description": "GitLab API client secret",
"required": false
},
"CMD_GITLAB_SCOPE": {
"description": "GitLab API client scope (optional)",
"required": false
},
"CMD_DROPBOX_CLIENTID": {
"description": "Dropbox API client id",
"required": false
},
"CMD_DROPBOX_CLIENTSECRET": {
"description": "Dropbox API client secret",
"required": false
},
"CMD_DROPBOX_APP_KEY": {
"description": "Dropbox app key (for import/export)",
"required": false
},
"CMD_GOOGLE_CLIENTID": {
"description": "Google API client id",
"required": false
},
"CMD_GOOGLE_CLIENTSECRET": {
"description": "Google API client secret",
"required": false
},
"CMD_GOOGLE_HOSTEDDOMAIN": {
"description": "Google API hosted domain (Provided only if the user belongs to a hosted domain)",
"required": false
},
"CMD_IMGUR_CLIENTID": {
"description": "Imgur API client id",
"required": false
}
},
"addons": [
"heroku-postgresql"
]
}

View file

@ -1,126 +0,0 @@
{
"test": {
"db": {
"dialect": "sqlite",
"storage": ":memory:"
},
"linkifyHeaderStyle": "gfm"
},
"development": {
"loglevel": "debug",
"hsts": {
"enable": false
},
"db": {
"dialect": "sqlite",
"storage": "./db.codimd.sqlite"
},
"linkifyHeaderStyle": "gfm"
},
"production": {
"domain": "localhost",
"loglevel": "info",
"hsts": {
"enable": true,
"maxAgeSeconds": 31536000,
"includeSubdomains": true,
"preload": true
},
"csp": {
"enable": true,
"directives": {
},
"upgradeInsecureRequests": "auto",
"addDefaults": true,
"addDisqus": true,
"addGoogleAnalytics": true
},
"db": {
"username": "",
"password": "",
"database": "codimd",
"host": "localhost",
"port": "5432",
"dialect": "postgres"
},
"facebook": {
"clientID": "change this",
"clientSecret": "change this"
},
"twitter": {
"consumerKey": "change this",
"consumerSecret": "change this"
},
"github": {
"clientID": "change this",
"clientSecret": "change this"
},
"gitlab": {
"baseURL": "change this",
"clientID": "change this",
"clientSecret": "change this",
"scope": "use 'read_user' scope for auth user only or remove this property if you need gitlab snippet import/export support (will result to be default scope 'api')",
"version": "use 'v4' if gitlab version > 11, 'v3' otherwise. Default to 'v4'"
},
"dropbox": {
"clientID": "change this",
"clientSecret": "change this",
"appKey": "change this"
},
"google": {
"clientID": "change this",
"clientSecret": "change this",
"apiKey": "change this"
},
"ldap": {
"url": "ldap://change_this",
"bindDn": null,
"bindCredentials": null,
"searchBase": "change this",
"searchFilter": "change this",
"searchAttributes": ["change this"],
"usernameField": "change this e.g. cn",
"useridField": "change this e.g. uid",
"tlsOptions": {
"changeme": "See https://nodejs.org/api/tls.html#tls_tls_connect_options_callback"
}
},
"saml": {
"idpSsoUrl": "change: authentication endpoint of IdP",
"idpCert": "change: certificate file path of IdP in PEM format",
"issuer": "change or delete: identity of the service provider (default: config.serverURL)",
"identifierFormat": "change or delete: name identifier format (default: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress')",
"disableRequestedAuthnContext": "change or delete: true to allow any authentication method, false restricts to password authentication method (default: false)",
"groupAttribute": "change or delete: attribute name for group list (ex: memberOf)",
"requiredGroups": [ "change or delete: group names that allowed" ],
"externalGroups": [ "change or delete: group names that not allowed" ],
"attribute": {
"id": "change or delete this: attribute map for `id` (default: NameID)",
"username": "change or delete this: attribute map for `username` (default: NameID)",
"email": "change or delete this: attribute map for `email` (default: NameID)"
}
},
"imgur": {
"clientID": "change this"
},
"minio": {
"accessKey": "change this",
"secretKey": "change this",
"endPoint": "change this",
"secure": true,
"port": 9000
},
"s3": {
"accessKeyId": "change this",
"secretAccessKey": "change this",
"region": "change this"
},
"s3bucket": "change this",
"azure":
{
"connectionString": "change this",
"container": "change this"
},
"linkifyHeaderStyle": "gfm"
}
}

View file

@ -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/<current commit>` | 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 path<sup>1</sup>, empty notes will be created with this template. |
| `dhParamPath` | `./cert/dhparam.pem` | SSL dhparam path<sup>1</sup> (only need when you set `useSSL`) |
| `sslCAPath` | `['./cert/COMODORSAAddTrustCA.crt']` | SSL ca chain<sup>1</sup> (only need when you set `useSSL`) |
| `sslCertPath` | `./cert/codimd_io.crt` | SSL cert path<sup>1</sup> (only need when you set `useSSL`) |
| `sslKeyPath` | `./cert/client.key` | SSL key path<sup>1</sup> (only need when you set `useSSL`) |
| `tmpPath` | `./tmp/` | temp directory path<sup>1</sup> |
| `docsPath` | `./public/docs` | docs directory path<sup>1</sup> |
| `viewPath` | `./public/views` | template directory path<sup>1</sup> |
| `uploadsPath` | `./public/uploads` | uploads directory<sup>1</sup> - needs to be persistent when you use imageUploadType `filesystem` |
| `localesPath` | `./locales` | directory for translations<sup>1</sup> |
## CodiMD Location
| variables | example values | description |
| --------- | ------ | ----------- |
| `domain` | `localhost` | domain name |
| `urlPath` | `codimd` | sub URL path, like `www.example.com/<urlpath>` |
| `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|
<sup>1</sup>: relative paths are based on CodiMD's base directory

View file

@ -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/<current commit>` | 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/<urlpath>` |
| `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://<someid>.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*

View file

@ -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/<current commit>` | 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 path<sup>1</sup>, empty notes will be
created with this template. | | `dhParamPath` | | **`undefined`**, `./cert/dhparam.pem` | SSL
dhparam path<sup>1</sup> (only need when you set `useSSL`) | | `sslCAPath` |
| **`undefined`**, `['./cert/COMODORSAAddTrustCA.crt']` | SSL ca chain<sup>1</sup> (only need when you set `useSSL`)
| | `sslCertPath` | | **`undefined`**, `./cert/hedgedoc_io.crt` | SSL cert path<sup>1</sup> (only need
when you set `useSSL`) | | `sslKeyPath` | | **`undefined`**
, `./cert/client.key` | SSL key path<sup>1</sup> (only need when you set `useSSL`)
| | `tmpPath` | | **`os.tmpdir()`**, `./tmp/` | temp directory path<sup>1</sup>
| | `docsPath` | | **`./public/docs`** | docs directory path<sup>1</sup>
| | `viewPath` | | **`./public/views`** | template directory path<sup>1</sup>
| | `uploadsPath` | | **`./public/uploads`** | uploads directory<sup>1</sup> - 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/<urlpath>` |
| `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://<someid>.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 |

64
docs/content/dev/api.md Normal file
View file

@ -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 *\<NOTE\>* with either the alias or id of a note you want to work on.
| Endpoint | HTTP-Method | Description |
| ---------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `/new` | `GET` | **Creates a new
note.**<br>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.**<br>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/<ALIAS>` | `POST` | **Imports some markdown data into a new note with a
given alias.**<br>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. | | `/<NOTE>/download`
or `/s/<SHORT-ID>/download` | `GET` | **Returns the raw markdown content of a note.**
| | `/<NOTE>/publish` | `GET` | **Redirects to the published version of the note.**
| | `/<NOTE>/slide` | `GET` | **Redirects to the slide-presentation of the
note.**<br>This is only useful on notes which are designed to be slides. | | `/<NOTE>/info`
| `GET` | **Returns metadata about the note.**<br>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. | | `/<NOTE>/revision`
| `GET` | **Returns a list of the available note revisions.**<br>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. |
| `/<NOTE>/revision/<REVISION-ID>` | `GET` | **Returns the revision of the note with some
metadata.**<br>The revision is returned as a JSON object with the content of the note and the authorship. |
| `/<NOTE>/gist` | `GET` | **Creates a new GitHub Gist with the note's
content.**<br>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.**<br>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.**<br>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.**<br>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/<NOTE>` | `POST` | **Toggles the pinned status in the history for a
note.**<br>The body must be form-encoded and contain a field `pinned` that is either `true` or `false`. |
| `/history/<NOTE>` | `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.**<br>The data is returned as a JSON object containing the number of notes stored on the server, (distinct) online users and more. |

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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=<super secret password>
@ -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: <https://www.npmjs.com/package/passport-ldapauth>

View file

@ -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
```

View file

@ -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

View file

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View file

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View file

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 113 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View file

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View file

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View file

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View file

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View file

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View file

Before

Width:  |  Height:  |  Size: 234 KiB

After

Width:  |  Height:  |  Size: 234 KiB

View file

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View file

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 180 KiB

View file

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View file

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View file

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View file

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 198 KiB

View file

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 187 KiB

View file

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.8 KiB

View file

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1564" height="1564" clip-rule="evenodd" fill-rule="evenodd"
stroke-linejoin="round" stroke-miterlimit="2">
<path
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1"
d="M781.965 0l-79.182 79.19-94.818-59.575-59.574 94.81-105.7-36.99-36.982 105.7-111.283-12.54-12.535 111.276-111.278 12.535 12.541 111.278-105.71 36.988 36.984 105.695-94.815 59.574 59.582 94.832L0 781.961l79.19 79.2-59.577 94.823 94.815 59.573-36.985 105.695 105.707 36.99-12.537 111.264 111.278 12.543 12.535 111.275 111.283-12.535 36.982 105.686 105.694-36.97 59.582 94.821 94.9-59.64 79.096 78.36 79.1-78.343 94.908 59.631 59.572-94.824 105.707 36.988 36.98-105.697 111.284 12.533 12.533-111.283 111.285-12.533-12.543-111.276 105.705-36.99-36.988-105.705 94.814-59.574-59.574-94.813 79.19-79.2-79.188-79.18 59.572-94.813-94.814-59.578 36.99-105.703-105.7-36.983 12.534-111.281-111.275-12.535-12.543-111.283-111.274 12.535-36.99-105.703-105.69 36.986-59.591-94.815-94.82 59.579zm0 77.785l71.305 71.307 85.394-53.656 53.666 85.384 95.172-33.302 33.31 95.185 100.206-11.289 11.296 100.217 100.205 11.289-11.287 100.213 95.182 33.3-33.309 95.188 85.385 53.654-53.648 85.381 71.312 71.309-71.31 71.318 11.666 18.569 41.978 66.812-85.383 53.647 33.311 95.193-95.195 33.31 11.297 100.205-100.215 11.288-11.287 100.216-100.215-11.287-33.301 95.182-95.193-33.31-53.649 85.394-85.289-53.588-18.094 17.922a106.956 106.956 0 0121.871 16.893c-.309 41.33-33.914 74.76-75.33 74.76-41.417 0-75.016-33.42-75.324-74.76a106.994 106.994 0 0122.069-17.01l-17.997-17.828-85.293 53.601-53.65-85.38-95.18 33.29-33.302-95.175-100.217 11.287-11.287-100.205-100.21-11.297 11.29-100.197-95.194-33.311 33.307-95.184-85.385-53.646 53.649-85.39-71.31-71.32 71.32-71.312-53.659-85.4 85.385-53.65-33.305-95.18 95.198-33.313-11.293-100.205 100.207-11.289 11.289-100.207 100.215 11.293 33.302-95.183 95.184 33.308 53.648-85.38 85.391 53.65z"
color="#000" font-weight="400" font-family="sans-serif" clip-rule="nonzero" overflow="visible" fill="#fff"
fill-rule="nonzero"/>
<path
d="M528.81 636.127c-145.441 0-263.341 117.905-263.341 263.342 0 76 32.23 144.43 83.72 192.49l357.635 357.443c19.257-19.156 45.746-30.984 74.996-30.984 29.295 0 55.839 11.871 75.1 31.09l348.266-348.49c52.88-49.77 92.25-120 92.25-200.1 0-145.437-117.9-263.34-263.34-263.34-72.24 0-137.68 29.112-185.252 76.225l-.033-.035-67.096 67.101-54.863-54.863c-48.267-55.067-119.07-89.88-198.041-89.88zm107.461 300.662c31.804 0 57.57 25.77 57.57 57.57s-25.766 57.569-57.57 57.569c-31.787 0-57.558-25.769-57.558-57.569 0-31.8 25.771-57.57 57.558-57.57zm291.944 0c31.8 0 57.57 25.77 57.57 57.57s-25.77 57.569-57.57 57.569c-31.79 0-57.567-25.769-57.567-57.569 0-31.8 25.777-57.57 57.567-57.57zm-146.27 587.695l.024.023.023-.023h-.047z"
fill="#fff" fill-rule="nonzero"/>
<path
d="M674.097 985.728c0 8.82-7.146 15.94-15.95 15.94-8.808 0-15.958-7.12-15.958-15.94 0-8.81 7.15-15.96 15.958-15.96 8.804 0 15.95 7.15 15.95 15.96m291.938 0c0 8.82-7.15 15.94-15.95 15.94-8.81 0-15.96-7.12-15.96-15.94 0-8.81 7.15-15.96 15.96-15.96 8.8 0 15.95 7.15 15.95 15.96"
fill="#fffffa" fill-rule="nonzero"/>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View file

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View file

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View file

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View file

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View file

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

View file

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

25
docs/content/index.md Normal file
View file

@ -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

View file

@ -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).

View file

@ -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:
```
<VirtualHost *:443>
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
</VirtualHost>
```

View file

@ -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).

View file

@ -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);
}

Some files were not shown because too many files have changed in this diff Show more