Move existing documentation to the new site

This commit is contained in:
Dmitry Verkhoturov
2021-06-27 14:53:20 -05:00
committed by Umputun
parent 68aba33765
commit 936ccd825f
24 changed files with 754 additions and 788 deletions
+2 -2
View File
@@ -629,7 +629,7 @@ communicating with demo server backend running on `https://demo.remark42.com`.
But you will not be able to login with any oauth providers due to security reasons.
You can attach to locally running backend by providing `REMARK_URL` environment variable.
```sh
```shell
npx cross-env REMARK_URL=http://127.0.0.1:8080 npm start
```
@@ -637,7 +637,7 @@ npx cross-env REMARK_URL=http://127.0.0.1:8080 npm start
to `./frontend` folder and rewrite variables as you wish. For such functional we use `dotenv`
The best way for start local developer environment:
```sh
```shell
cp compose-dev-frontend.yml compose-private-frontend.yml
docker-compose -f compose-private-frontend.yml up --build
cd frontend
-14
View File
@@ -1,14 +0,0 @@
---
title: Email templating
---
Remark42 uses golang templates for email templating. Templates are located in `backend/templates` and embedded into binary by statik
For getting access to the files you can use package `templates` from `backend/app/templates`
Now we have following templates:
- `email_confirmation_login.html.tmpl` used for confirmation of login
- `email_confirmation_subscription.html.tmpl` used for confirmation of subscription
`email_reply.html.tmpl` used for sending replies to user comments (when user subscribed to it) and for noticing admins about new comments on a site
`email_unsubscribe.html.tmpl` used for notification about successful unsubscribe from replies
`error_response.html.tmpl` used for ...
-215
View File
@@ -1,215 +0,0 @@
---
title: Email
---
## Overview
This documentation describes how to enable the email-related capabilities of Remark.
- email authentication for users:
enabling this will let the user log in using their emails:
![Email authentication](/docs/images/email_auth.png?raw=true)
- email notifications for any users except anonymous:
GitHub or Google or Twitter or any other kind of user gets the ability to get
email notifications about new replies to their comments (and any of the replies down the tree):
![Email notifications subscription](/docs/images/email_notifications.png?raw=true)
## Setup email server connection
To enable any of email functionality you need to set up email
(SMTP) server connection using these variables:
```
SMTP_HOST
SMTP_PORT
SMTP_TLS
SMTP_USERNAME
SMTP_PASSWORD
SMTP_TIMEOUT
```
### Mailgun
This is an example of a configuration using [Mailgun](https://www.mailgun.com/) email service:
```yaml
- SMTP_HOST=smtp.eu.mailgun.org
- SMTP_PORT=465
- SMTP_TLS=true
- SMTP_USERNAME=postmaster@mg.example.com
- SMTP_PASSWORD=secretpassword
- AUTH_EMAIL_FROM=notify@example.com
- NOTIFY_EMAIL_FROM=notify@example.com
```
#### API
When you don't want to expose your IP (which is impossible with any SMTP provider)
and for situations when connecting to external SMTP server is impossible due to firewall
settings is setting up an SMTP-to-API bridge and sending messages through it.
To use any of containers below with in remark42 environment set following two `SMTP` variables:
```yaml
- SMTP_HOST=mail
- SMTP_PORT=25
```
#### stevenolen/mailgun-smtp-server
Here is `docker-compose.yml` configuration part spinning up a container for
[stevenolen/mailgun-smtp-server](https://hub.docker.com/r/stevenolen/mailgun-smtp-server):
```yaml
mailgun:
image: stevenolen/mailgun-smtp-server
container_name: 'mail'
hostname: 'mail'
logging:
driver: json-file
options:
max-size: '10m'
max-file: '5'
environment:
- MG_KEY=key-123456789
- MG_DOMAIN=example.com
```
Please note that before
[stevenolen/mailgun-smtp-server#5](https://github.com/stevenolen/mailgun-smtp-server/issues/5)
is fixed, Europe domain names are not supported by this tool.
### SendGrid
This is an example of a configuration using [SendGrid](https://sendgrid.com/) email service:
```yaml
- SMTP_HOST=smtp.sendgrid.net
- SMTP_PORT=465
- SMTP_TLS=true
- SMTP_USERNAME=apikey
- SMTP_PASSWORD=key-123456789
- AUTH_EMAIL_FROM=notify@example.com
- NOTIFY_EMAIL_FROM=notify@example.com
```
#### API
When you don't want to expose your IP (which is impossible with any SMTP provider)
and for situations when connecting to external SMTP server is impossible due to firewall
settings is setting up an SMTP-to-API bridge and sending messages through it.
To use any of containers below with in remark42 environment set following two `SMTP` variables:
```yaml
- SMTP_HOST=mail
- SMTP_PORT=25
```
#### fgribreau/smtp-to-sendgrid-gateway
Here is `docker-compose.yml` configuration part spinning up a container for
[fgribreau/smtp-to-sendgrid-gateway](https://hub.docker.com/r/fgribreau/smtp-to-sendgrid-gateway):
```yaml
sendgrid:
image: fgribreau/smtp-to-sendgrid-gateway
container_name: 'mail'
hostname: 'mail'
logging:
driver: json-file
options:
max-size: '10m'
max-file: '5'
environment:
- SENDGRID_API=key-123456789
```
### Gmail
Configuration example for Gmail:
```yaml
- SMTP_HOST=smtp.gmail.com
- SMTP_PORT=465
- SMTP_TLS=true
- SMTP_USERNAME=example.user@gmail.com
- SMTP_PASSWORD=secretpassword
- AUTH_EMAIL_FROM=example.user@gmail.com
- NOTIFY_EMAIL_FROM=example.user@gmail.com
```
### Amazon SES
Configuration example for [Amazon SES](https://aws.amazon.com/ses/) (us-east-1 region):
```yaml
- SMTP_HOST=email-smtp.us-east-1.amazonaws.com
- SMTP_PORT=465
- SMTP_TLS=true
- SMTP_USERNAME=access_key_id
- SMTP_PASSWORD=secret_access_key
- AUTH_EMAIL_FROM=notify@example.com
- NOTIFY_EMAIL_FROM=notify@example.com
```
A domain or an email that will be used in `AUTH_EMAIL_FROM` or `NOTIFY_EMAIL_FROM`
must first be [verified](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-domain-procedure.html).
[SMTP Credentials](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html)
must first be obtained from
[Amazon SES Console](https://console.aws.amazon.com/ses/home?region=us-east-1#smtp-settings:):
## Setup email authentication
Here is the list of variables which affect email authentication:
```
AUTH_EMAIL_ENABLE
AUTH_EMAIL_FROM
AUTH_EMAIL_SUBJ
AUTH_EMAIL_CONTENT_TYPE
AUTH_EMAIL_TEMPLATE
```
After you set `SMTP_` variables, you can allow email authentication by setting these two variables:
```yaml
- AUTH_EMAIL_ENABLE=true
- AUTH_EMAIL_FROM=notify@example.com
```
Usually, you don't need to change/set anything else. In case if you want to use a different
email template set `AUTH_EMAIL_TEMPLATE`, for instance
`- AUTH_EMAIL_TEMPLATE="Confirmation email, token: {{.Token}}"`.
See [verified-authentication](https://github.com/go-pkgz/auth#verified-authentication) for more details.
## Setup email notifications
Here is the list of variables which affect email notifications:
```yaml
NOTIFY_USERS
NOTIFY_EMAIL_FROM
NOTIFY_EMAIL_VERIFICATION_SUBJ
# for administrator notifications for new comments on their site
ADMIN_SHARED_EMAIL
NOTIFY_ADMINS
```
After you set `SMTP_` variables, you can allow email notifications by setting these two variables:
```yaml
- NOTIFY_USERS=email
# - NOTIFY_USERS=email,telegram # this is in case you want to have both email and telegram notifications enabled
- NOTIFY_EMAIL_FROM=notify@example.com
```
-10
View File
@@ -1,10 +0,0 @@
# Documentation and FAQ
- [How to configure remark42 with nginx reverse proxy](nginx-proxy)
- [How to configure remark42 without a subdomain](subdomain) with Nginx or Caddy
- [How to configure remark42 for Single Page Apps (SPA)](spa)
- [Telegram notifications](telegram)
- [Slack notifications](slack)
- [Setup email authentication and\or email notifications](email)
- [How to add new translation to remark42](translation)
- [How to run remark42 on Kubernetes](kubernetes)
-171
View File
@@ -1,171 +0,0 @@
---
title: Running remark42 in Kubernetes
---
## Using Helm
Use [remark42 Helm chart](https://github.com/groundhog2k/helm-charts/tree/master/charts/remark42).
## Without Helm
Here's the sample manifest for running remark42 on Hetzner Cloud:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: remark42
namespace: remark42
labels:
app: remark42
spec:
replicas: 1
selector:
matchLabels:
app: remark42
strategy:
type: Recreate
template:
metadata:
namespace: remark42
labels:
app: remark42
spec:
containers:
- name: remark42
image: umputun/remark42:v1.8.1
ports:
# http:
- containerPort: 8080
env:
- name: REMARK_URL
value: "https://comments.mysite.com/"
- name: "SITE"
value: "mysite.com"
- name: SECRET
valueFrom:
secretKeyRef:
name: remark42
key: SECRET
- name: STORE_BOLT_PATH
value: "/srv/var/db"
- name: BACKUP_PATH
value: "/srv/var/backup"
- name: AUTH_GOOGLE_CID
valueFrom:
secretKeyRef:
name: remark42
key: AUTH_GOOGLE_CID
- name: AUTH_GOOGLE_CSEC
valueFrom:
secretKeyRef:
name: remark42
key: AUTH_GOOGLE_CSEC
- name: AUTH_GITHUB_CID
valueFrom:
secretKeyRef:
name: remark42
key: AUTH_GITHUB_CID
- name: AUTH_GITHUB_CSEC
valueFrom:
secretKeyRef:
name: remark42
key: AUTH_GITHUB_CSEC
- name: ADMIN_SHARED_ID
value: "google_b182b5daa0004104b348d9bde762b1880ed9d98d"
- name: TIME_ZONE
value: "Europe/Dublin"
volumeMounts:
- name: srvvar
mountPath: /srv/var
securityContext:
readOnlyRootFilesystem: false
resources:
requests:
cpu: "100m"
memory: "25Mi"
limits:
cpu: "1"
memory: "1Gi"
securityContext:
# Has its own root privilege drop. Can't do runAsUser / runAsGroup.
volumes:
- name: srvvar
persistentVolumeClaim:
claimName: remark42
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: remark42
namespace: remark42
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: hcloud-volumes
---
apiVersion: v1
kind: Service
metadata:
name: remark42-web
namespace: remark42
spec:
selector:
app: remark42
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
---
# TODO: switch to networking.k8s.io/v1
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: remark42-ingress
namespace: remark42
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- comments.mysite.com
secretName: comments-tls
rules:
- host: "comments.mysite.com"
http:
paths:
- path: /
pathType: Prefix
backend:
serviceName: remark42-web
servicePort: 8080
```
Change `storageClassName` if you run on top of different cloud / bare metal.
This example assumes there is nginx Ingress with cert-manager already set up.
Adjust accordingly if you use different Ingress.
In addition you'd need to define secrets, e.g.
```yaml
apiVersion: v1
kind: Secret
metadata:
name: remark42
namespace: remark42
stringData:
SECRET: <changeme>
AUTH_GOOGLE_CID: <changeme>.apps.googleusercontent.com
AUTH_GOOGLE_CSEC: <changeme>
AUTH_GITHUB_CID: <changeme>
AUTH_GITHUB_CSEC: <changeme>
```
Some more information (and comments!) may be found
[here](https://www.rusinov.ie/en/posts/2021/this-website-has-remark42-comments-now/).
-30
View File
@@ -1,30 +0,0 @@
---
title: Site URL migration
---
Here is an example on how to move your comments after your posts are moved, from `https://example.org/blog/<slug>` to `https://example.org/post/<slug>` in that example.
### Rules file
First you have to create a `rules` file in remark's `/var` folder.
[Here is the test](https://github.com/akosourov/remark/blob/4dc123dbe84f4f248864bcdbbd6cc2b3a4dafe11/backend/app/migrator/mapper_test.go#L13-L17) with an example of rules file syntax, format is simply `old_url new_url` like following:
```
https://example.org/old-url-1/ https://example.org/new-url-1/
https://example.org/old-url-2/ https://example.org/new-url-2/
```
### Applying the remap
After rules file is ready, run the following command:
```sh
remark42 remap --admin-passwd <password> -f var/rules
```
If running in a docker container, the command becomes:
```sh
docker ps # to find the container name
docker exec -it <container> remark42 remap --admin-passwd <password> -f var/rules
```
-54
View File
@@ -1,54 +0,0 @@
---
title: Nginx
---
## How to configure remark42 with nginx reverse proxy
Example of nginx configuration (reverse proxy) running remark42 service on remark42.example.com
```nginx
server {
listen 443;
server_name remark42.example.com;
ssl on;
ssl_certificate /etc/nginx/ssl/remark42.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/remark42.example.com.key;
gzip on;
gzip_types text/plain application/json text/css application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml;
gzip_min_length 1000;
gzip_proxied any;
location ~ /\.git {
deny all;
}
location /index.html {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://remark42:8080/web/index.html;
}
location / {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://remark42:8080/;
}
access_log /var/log/nginx/remark42.log;
}
server {
listen 80;
server_name remark42.example.com;
return 301 https://remark42.example.com$request_uri;
}
```
note: `proxy_pass` points to internal DNS name `remark42` and expected to run from the same compose. If nginx runs outside compose the real IP (or docker's bridge IP) should be used
-40
View File
@@ -1,40 +0,0 @@
---
title: Slack
---
## Slack notifications
In order to integrate notifications from remark42 with the [slack](https://slack.com), you should create [a bot](https://slack.com/intl/en-cn/help/articles/115005265703-Create-a-bot-for-your-workspace) and obtain a token.
### Create a Slack Bot
1. Create a [Slack app](https://api.slack.com/apps/new) if you don't already have one, or select an existing app you've created.
2. Click the OAuth & Permissions tab in the left sidebar.
3. Below Bot Token Scopes, select the `chat:write`, `chat:write.public` and `channels:read` scopes. Then click Add an OAuth Scope.
4. Scroll to the top of the page, and click on Install to workspace.
5. You should see the "_View basic information about public channels in your workspace_", "_Send Message as ..._" and "_Send messages to channels ... isn't a member of_" as the permission, then click allow.
6. You can then see you token, in the form of `xoxb-...-...-...`
### Remark42 configuration
The slack token which you obtained before should be used as `NOTIFY_SLACK_TOKEN`.
You also need to set `NOTIFY_ADMINS=slack` for the Slack notification to be active.
By default, the notification are sent to the `general` channel on slack. If you need another channel, you can specify it, for instance with `NOTIFY_SLACK_CHAN=random`.
```
- NOTIFY_ADMINS=slack
- NOTIFY_SLACK_CHAN=general
- NOTIFY_SLACK_TOKEN=xoxb-....
```
### Verify the notifications on Slack
If all goes fine, you should be able to see the following message on your Slack notification channel:
> New comment from _author_ -> _original author_
>> [Demo | Remark42](http://127.0.0.1:8080/web/#remark42__comment-11288987987)
>> This is the comment written by _author_
-72
View File
@@ -1,72 +0,0 @@
---
title: SPA
---
## How to configure remark42 for Single Page Apps (SPA)
Originally tested on [Nuxt.js](https://nuxtjs.org/), but it should be applicable to all SPAs.
- Add the following JavaScript to your `index.html`, which in this case, it is identical to `<script defer src="$HOST/web/embed.js"></script>`
```js
;(function () {
var host = // Your remark42 host
var components = ['embed'] // Your choice of remark42 components
;(function(c) {
for (let i = 0; i < c.length; i++) {
const d = document
const s = d.createElement('script')
s.src = remark_config.host + '/web/' + c[i] + '.js'
s.defer = true
;(d.head || d.body).appendChild(s)
}
})(components)
})
```
- Created `remark42Instance` when the `div` containing remark42 has appeared, usually at `mounted` or `componentDidMount` of the SPA lifecycle. Destroy the previous instance first, if necessary.
```ts
initRemark42() {
if (window.REMARK42) {
if (this.remark42Instance) {
this.remark42Instance.destroy()
}
this.remark42Instance = window.REMARK42.createInstance({
node: this.$refs.remark42 as HTMLElement,
...remark42_config // See <https://github.com/patarapolw/remark42#setup-on-your-website>
})
}
}
mounted() {
if (window.REMARK42) {
this.initRemark42()
} else {
window.addEventListener('REMARK42::ready', () => {
this.initRemark42()
})
}
}
```
- Ensure that this is called every time route changes
```ts
@Watch('$route.path')
onRouteChange() {
this.initRemark42()
}
```
- And, destroyed before routeLeave
```ts
beforeRouteLeave() {
if (this.remark42Instance) {
this.remark42Instance.destroy()
}
}
```
-77
View File
@@ -1,77 +0,0 @@
---
title: Subdomain
---
## How to configure remark42 without a subdomain
All README examples show configurations with remark42 on its own subdomain, i.e. `https://remark42.example.com`. However, it is possible and sometimes desirable to run remark42 without a subdomain, but just under some path, i.e. `https://example.com/remark42`.
- The frontend URL looks like this: `s.src = 'https://example.com/remark42/web/embed.js;`
- The backend `REMARK_URL` parameter will be `https://example.com/remark42`
- And you also need to slightly modify the callback URL for the social media login API's:
- Facebook Valid OAuth Redirect URIs: `https://example.com/remark42/auth/facebook/callback`
- Google Authorized redirect URIs: `https://example.com/remark42/auth/google/callback`
- GitHub Authorised callback URL: `https://example.com/remark42/auth/github/callback`
### docker-compose configuration
Both Nginx and Caddy configuration below relies on remark42 available on hostname `remark42`, which is achieved by having `container_name: remark42` in docker-compose.
Example `docker-compose.yaml`:
```yaml
version: '2'
services:
remark42:
image: umputun/remark42:latest
container_name: remark42
restart: always
environment:
- REMARK_URL=https://example.com/remark42/
- SITE=<site_ID>
- SECRET=<secret>
- ADMIN_SHARED_ID=<shared_id>
volumes:
- ./data:/srv/var
logging:
options:
max-size: '10m'
max-file: '1'
```
### Nginx configuration
The `nginx.conf` would then look something like:
```
location /remark42/ {
rewrite /remark42/(.*) /$1 break;
proxy_pass http://remark42:8080/; // use internal docker name of remark42 container for proxy
proxy_set_header Host $http_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;
}
```
### Caddy configuration
Example of Caddy configuration (`Caddyfile`) running remark42 service on `example.com/remark42/`:
```caddy
example.com {
gzip
tls mail@example.com
root /srv/www
log /logs/access.log
# remark42
proxy /remark42/ http://remark42:8080/ {
without /remark42
transparent
}
}
```
-41
View File
@@ -1,41 +0,0 @@
---
title: Telegram
---
## Telegram notifications for administrators
In order to integrate notifications about any comment on your sites with remark42 with [telegram](https://telegram.org)
1. Set `NOTIFY_ADMINS=telegram`
1. Make [a channel](https://telegram.org/faq_channels) and add it to remark42 configuration as `NOTIFY_TELEGRAM_CHAN`
1. Get a token according to the instruction below and add it to the configuration as well
## Getting token for Telegram
In order to get token "just talk to [BotFather](https://core.telegram.org/bots#6-botfather)". All you need is to send `/newbot` command, and choose the name for your bot (it must end in `bot`). This is it, you got a token which you'll need to write down into remark42 configuration as `TELEGRAM_TOKEN`.
_Example of such a "talk":_
```
Umputun:
/newbot
BotFather:
Alright, a new bot. How are we going to call it? Please choose a name for your bot.
Umputun:
example_comments
BotFather:
Good. Now let's choose a username for your bot. It must end in `bot`. Like this, for example: TetrisBot or tetris_bot.
Umputun:
example_comments_bot
BotFather:
Done! Congratulations on your new bot. You will find it at t.me/example_comments_bot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. By the way, when you've finished creating your cool bot, ping our Bot Support if you want a better username for it. Just make sure the bot is fully operational before you do this.
Use this token to access the HTTP API:
12345678:xy778Iltzsdr45tg
For a description of the Bot API, see this page: https://core.telegram.org/bots/api
```
-58
View File
@@ -1,58 +0,0 @@
---
title: Translation
---
## How to add new language translation to Remark42
Translation files are stored in [/frontend/app/locales](https://github.com/umputun/remark42/tree/master/frontend/app/locales)
directory with `.json` extension and content like following:
```json
{
"anonymousLoginForm.length-limit": "Username must be at least 3 characters long",
"anonymousLoginForm.log-in": "Log in",
"anonymousLoginForm.symbol-limit": "Username must start from the letter and contain only latin letters, numbers, underscores, and spaces",
<...>
}
```
### How to add a new translation
We truly appreciate people spending time contributing their translations to remark42. Please go through the steps
below in order to have your translation start being available to all remark42 users and included in the next release.
1. create a fork of [umputun/remark42](https://github.com/umputun/remark42) repo, and if you already have one please
pull the latest changes from the upstream master branch. It could be done like that:
```shell
git remote add upstream https://github.com/umputun/remark42.git
git fetch upstream
git rebase upstream/master
git push
```
1. add a new locale with [two-letter code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
of the language you want to make the translation into to list in
[frontend/tasks/supportedLocales.json](https://github.com/umputun/remark42/blob/master/frontend/tasks/supportedLocales.json)
1. run `npm install` in `frontend` folder
1. run `npm run translation:extract` in `frontend` folder
1. run `npm run translation:generate` in `frontend` folder
1. translate all values in the newly created json file in
[frontend/app/locales/](https://github.com/umputun/remark42/blob/master/frontend/app/locales/)
1. commit all changes above in your fork
1. test your changes in the interface:
1. uncomment `locale: "ru"` line in [frontend/index.ejs](https://github.com/umputun/remark42/blob/master/frontend/index.ejs#L133)
and replace `ru` with your translation language code
1. [run remark42 in Docker](https://github.com/umputun/remark42#development) by issuing following commands
from the root directory of your remark42 fork:
```shell
docker-compose -f compose-dev-frontend.yml build
docker-compose -f compose-dev-frontend.yml up
```
1. open [http://127.0.0.1:8080/web](http://127.0.0.1:8080/web), log in, make a comment, make a reply to a comment,
and make sure your translation looks as you expect it to look
1. make a screenshot from [http://127.0.0.1:8080](http://127.0.0.1:8080) with your translation in place
1. after all previous steps are done, create a [Pull Request](https://github.com/umputun/remark42/pulls) to umputun/remark42
repo with your changes, attaching a screenshot or two from your local test instance to it
@@ -0,0 +1,32 @@
---
title: Site URL migration
parent: Backup
order: 400
---
Here is an example on how to move your comments after your posts are moved, from `https://example.org/blog/<slug>` to `https://example.org/post/<slug>` in that example.
### Rules file
First you have to create a `rules` file in remark's `/var` folder.
Format is simply `old_url new_url` like following:
```
https://example.org/old-url-1/ https://example.org/new-url-1/
https://example.org/old-url-2/ https://example.org/new-url-2/
```
### Applying the remap
After rules file is ready, run the following command:
```shell
remark42 remap --admin-passwd <password> -f var/rules
```
If running in a docker container, the command becomes:
```shell
docker ps # to find the container name
docker exec -it <container> remark42 remap --admin-passwd <password> -f var/rules
```

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

+225
View File
@@ -4,3 +4,228 @@ menuTitle: Email
parent: Configuration
order: 300
---
## Overview
This documentation describes how to enable the email-related capabilities of Remark.
- email authentication for users:
enabling this will let the user log in using their emails:
![Email authentication](email_auth.png?raw=true)
- email notifications for any users except anonymous:
GitHub or Google or Twitter or any other kind of user gets the ability to get
email notifications about new replies to their comments (and any of the replies down the tree):
![Email notifications subscription](email_notifications.png?raw=true)
## Setup email server connection
To enable any of email functionality you need to set up email
(SMTP) server connection using these variables:
```
SMTP_HOST
SMTP_PORT
SMTP_TLS
SMTP_USERNAME
SMTP_PASSWORD
SMTP_TIMEOUT
```
### Mailgun
This is an example of a configuration using [Mailgun](https://www.mailgun.com/) email service:
```yaml
- SMTP_HOST=smtp.eu.mailgun.org
- SMTP_PORT=465
- SMTP_TLS=true
- SMTP_USERNAME=postmaster@mg.example.com
- SMTP_PASSWORD=secretpassword
- AUTH_EMAIL_FROM=notify@example.com
- NOTIFY_EMAIL_FROM=notify@example.com
```
#### API
When you don't want to expose your IP (which is impossible with any SMTP provider)
and for situations when connecting to external SMTP server is impossible due to firewall
settings is setting up an SMTP-to-API bridge and sending messages through it.
To use any of containers below with in remark42 environment set following two `SMTP` variables:
```yaml
- SMTP_HOST=mail
- SMTP_PORT=25
```
#### stevenolen/mailgun-smtp-server
Here is `docker-compose.yml` configuration part spinning up a container for
[stevenolen/mailgun-smtp-server](https://hub.docker.com/r/stevenolen/mailgun-smtp-server):
```yaml
mailgun:
image: stevenolen/mailgun-smtp-server
container_name: 'mail'
hostname: 'mail'
logging:
driver: json-file
options:
max-size: '10m'
max-file: '5'
environment:
- MG_KEY=key-123456789
- MG_DOMAIN=example.com
```
Please note that before
[stevenolen/mailgun-smtp-server#5](https://github.com/stevenolen/mailgun-smtp-server/issues/5)
is fixed, Europe domain names are not supported by this tool.
### SendGrid
This is an example of a configuration using [SendGrid](https://sendgrid.com/) email service:
```yaml
- SMTP_HOST=smtp.sendgrid.net
- SMTP_PORT=465
- SMTP_TLS=true
- SMTP_USERNAME=apikey
- SMTP_PASSWORD=key-123456789
- AUTH_EMAIL_FROM=notify@example.com
- NOTIFY_EMAIL_FROM=notify@example.com
```
#### API
When you don't want to expose your IP (which is impossible with any SMTP provider)
and for situations when connecting to external SMTP server is impossible due to firewall
settings is setting up an SMTP-to-API bridge and sending messages through it.
To use any of containers below with in remark42 environment set following two `SMTP` variables:
```yaml
- SMTP_HOST=mail
- SMTP_PORT=25
```
#### fgribreau/smtp-to-sendgrid-gateway
Here is `docker-compose.yml` configuration part spinning up a container for
[fgribreau/smtp-to-sendgrid-gateway](https://hub.docker.com/r/fgribreau/smtp-to-sendgrid-gateway):
```yaml
sendgrid:
image: fgribreau/smtp-to-sendgrid-gateway
container_name: 'mail'
hostname: 'mail'
logging:
driver: json-file
options:
max-size: '10m'
max-file: '5'
environment:
- SENDGRID_API=key-123456789
```
### Gmail
Configuration example for Gmail:
```yaml
- SMTP_HOST=smtp.gmail.com
- SMTP_PORT=465
- SMTP_TLS=true
- SMTP_USERNAME=example.user@gmail.com
- SMTP_PASSWORD=secretpassword
- AUTH_EMAIL_FROM=example.user@gmail.com
- NOTIFY_EMAIL_FROM=example.user@gmail.com
```
### Amazon SES
Configuration example for [Amazon SES](https://aws.amazon.com/ses/) (us-east-1 region):
```yaml
- SMTP_HOST=email-smtp.us-east-1.amazonaws.com
- SMTP_PORT=465
- SMTP_TLS=true
- SMTP_USERNAME=access_key_id
- SMTP_PASSWORD=secret_access_key
- AUTH_EMAIL_FROM=notify@example.com
- NOTIFY_EMAIL_FROM=notify@example.com
```
A domain or an email that will be used in `AUTH_EMAIL_FROM` or `NOTIFY_EMAIL_FROM`
must first be [verified](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-domain-procedure.html).
[SMTP Credentials](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html)
must first be obtained from
[Amazon SES Console](https://console.aws.amazon.com/ses/home?region=us-east-1#smtp-settings:):
## Setup email authentication
Here is the list of variables which affect email authentication:
```
AUTH_EMAIL_ENABLE
AUTH_EMAIL_FROM
AUTH_EMAIL_SUBJ
AUTH_EMAIL_CONTENT_TYPE
AUTH_EMAIL_TEMPLATE
```
After you set `SMTP_` variables, you can allow email authentication by setting these two variables:
```yaml
- AUTH_EMAIL_ENABLE=true
- AUTH_EMAIL_FROM=notify@example.com
```
Usually, you don't need to change/set anything else. In case if you want to use a different
email template set `AUTH_EMAIL_TEMPLATE`, for instance
`- AUTH_EMAIL_TEMPLATE="Confirmation email, token: {{.Token}}"`.
See [verified-authentication](https://github.com/go-pkgz/auth#verified-authentication) for more details.
## Setup email notifications
Here is the list of variables which affect email notifications:
```yaml
NOTIFY_USERS
NOTIFY_EMAIL_FROM
NOTIFY_EMAIL_VERIFICATION_SUBJ
# for administrator notifications for new comments on their site
ADMIN_SHARED_EMAIL
NOTIFY_ADMINS
```
After you set `SMTP_` variables, you can allow email notifications by setting these two variables:
```yaml
- NOTIFY_USERS=email
# - NOTIFY_USERS=email,telegram # this is in case you want to have both email and telegram notifications enabled
- NOTIFY_EMAIL_FROM=notify@example.com
```
## Email messages templates
Remark42 uses golang templates for email templating. Templates are located in `backend/templates` and embedded into binary by statik
For getting access to the files you can use package `templates` from `backend/app/templates`
Now we have following templates:
- `email_confirmation_login.html.tmpl` used for confirmation of login
- `email_confirmation_subscription.html.tmpl` used for confirmation of subscription
`email_reply.html.tmpl` used for sending replies to user comments (when user subscribed to it) and for noticing admins about new comments on a site
`email_unsubscribe.html.tmpl` used for notification about successful unsubscribe from replies
`error_response.html.tmpl` used for ...
@@ -14,3 +14,73 @@ order: 100
### Last comments widget
## API for Single-Page Applications
## How to configure remark42 for Single Page Apps (SPA)
Originally tested on [Nuxt.js](https://nuxtjs.org/), but it should be applicable to all SPAs.
- Add the following JavaScript to your `index.html`, which in this case, it is identical to `<script defer src="$HOST/web/embed.js"></script>`
```js
;(function () {
var host = // Your remark42 host
var components = ['embed'] // Your choice of remark42 components
;(function(c) {
for (let i = 0; i < c.length; i++) {
const d = document
const s = d.createElement('script')
s.src = remark_config.host + '/web/' + c[i] + '.js'
s.defer = true
;(d.head || d.body).appendChild(s)
}
})(components)
})
```
- Created `remark42Instance` when the `div` containing remark42 has appeared, usually at `mounted` or `componentDidMount` of the SPA lifecycle. Destroy the previous instance first, if necessary.
```ts
initRemark42() {
if (window.REMARK42) {
if (this.remark42Instance) {
this.remark42Instance.destroy()
}
this.remark42Instance = window.REMARK42.createInstance({
node: this.$refs.remark42 as HTMLElement,
...remark42_config // See <https://github.com/patarapolw/remark42#setup-on-your-website>
})
}
}
mounted() {
if (window.REMARK42) {
this.initRemark42()
} else {
window.addEventListener('REMARK42::ready', () => {
this.initRemark42()
})
}
}
```
- Ensure that this is called every time route changes
```ts
@Watch('$route.path')
onRouteChange() {
this.initRemark42()
}
```
- And, destroyed before routeLeave
```ts
beforeRouteLeave() {
if (this.remark42Instance) {
this.remark42Instance.destroy()
}
}
```
@@ -4,3 +4,171 @@ menuTitle: Kubernetes
parent: Configuration
order: 700
---
## Using Helm
Use [remark42 Helm chart](https://github.com/groundhog2k/helm-charts/tree/master/charts/remark42).
## Without Helm
Here's the sample manifest for running remark42 on Hetzner Cloud:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: remark42
namespace: remark42
labels:
app: remark42
spec:
replicas: 1
selector:
matchLabels:
app: remark42
strategy:
type: Recreate
template:
metadata:
namespace: remark42
labels:
app: remark42
spec:
containers:
- name: remark42
image: umputun/remark42:v1.8.1
ports:
# http:
- containerPort: 8080
env:
- name: REMARK_URL
value: "https://comments.mysite.com/"
- name: "SITE"
value: "mysite.com"
- name: SECRET
valueFrom:
secretKeyRef:
name: remark42
key: SECRET
- name: STORE_BOLT_PATH
value: "/srv/var/db"
- name: BACKUP_PATH
value: "/srv/var/backup"
- name: AUTH_GOOGLE_CID
valueFrom:
secretKeyRef:
name: remark42
key: AUTH_GOOGLE_CID
- name: AUTH_GOOGLE_CSEC
valueFrom:
secretKeyRef:
name: remark42
key: AUTH_GOOGLE_CSEC
- name: AUTH_GITHUB_CID
valueFrom:
secretKeyRef:
name: remark42
key: AUTH_GITHUB_CID
- name: AUTH_GITHUB_CSEC
valueFrom:
secretKeyRef:
name: remark42
key: AUTH_GITHUB_CSEC
- name: ADMIN_SHARED_ID
value: "google_b182b5daa0004104b348d9bde762b1880ed9d98d"
- name: TIME_ZONE
value: "Europe/Dublin"
volumeMounts:
- name: srvvar
mountPath: /srv/var
securityContext:
readOnlyRootFilesystem: false
resources:
requests:
cpu: "100m"
memory: "25Mi"
limits:
cpu: "1"
memory: "1Gi"
securityContext:
# Has its own root privilege drop. Can't do runAsUser / runAsGroup.
volumes:
- name: srvvar
persistentVolumeClaim:
claimName: remark42
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: remark42
namespace: remark42
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: hcloud-volumes
---
apiVersion: v1
kind: Service
metadata:
name: remark42-web
namespace: remark42
spec:
selector:
app: remark42
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
---
# TODO: switch to networking.k8s.io/v1
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: remark42-ingress
namespace: remark42
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- comments.mysite.com
secretName: comments-tls
rules:
- host: "comments.mysite.com"
http:
paths:
- path: /
pathType: Prefix
backend:
serviceName: remark42-web
servicePort: 8080
```
Change `storageClassName` if you run on top of different cloud / bare metal.
This example assumes there is nginx Ingress with cert-manager already set up.
Adjust accordingly if you use different Ingress.
In addition you'd need to define secrets, e.g.
```yaml
apiVersion: v1
kind: Secret
metadata:
name: remark42
namespace: remark42
stringData:
SECRET: <changeme>
AUTH_GOOGLE_CID: <changeme>.apps.googleusercontent.com
AUTH_GOOGLE_CSEC: <changeme>
AUTH_GITHUB_CID: <changeme>
AUTH_GITHUB_CSEC: <changeme>
```
Some more information (and comments!) may be found
[here](https://www.rusinov.ie/en/posts/2021/this-website-has-remark42-comments-now/).
@@ -4,3 +4,54 @@ menuTitle: Nginx
parent: Configuration
order: 500
---
## How to configure remark42 with nginx reverse proxy
Example of nginx configuration (reverse proxy) running remark42 service on remark42.example.com
```nginx
server {
listen 443;
server_name remark42.example.com;
ssl on;
ssl_certificate /etc/nginx/ssl/remark42.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/remark42.example.com.key;
gzip on;
gzip_types text/plain application/json text/css application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml;
gzip_min_length 1000;
gzip_proxied any;
location ~ /\.git {
deny all;
}
location /index.html {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://remark42:8080/web/index.html;
}
location / {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://remark42:8080/;
}
access_log /var/log/nginx/remark42.log;
}
server {
listen 80;
server_name remark42.example.com;
return 301 https://remark42.example.com$request_uri;
}
```
note: `proxy_pass` points to internal DNS name `remark42` and expected to run from the same compose. If nginx runs outside compose the real IP (or docker's bridge IP) should be used
@@ -6,6 +6,78 @@ order: 400
## Email
## Slack
## Slack admin notifications
In order to integrate notifications from remark42 with the [slack](https://slack.com), you should create [a bot](https://slack.com/intl/en-cn/help/articles/115005265703-Create-a-bot-for-your-workspace) and obtain a token.
### Create a Slack Bot
1. Create a [Slack app](https://api.slack.com/apps/new) if you don't already have one, or select an existing app you've created.
2. Click the OAuth & Permissions tab in the left sidebar.
3. Below Bot Token Scopes, select the `chat:write`, `chat:write.public` and `channels:read` scopes. Then click Add an OAuth Scope.
4. Scroll to the top of the page, and click on Install to workspace.
5. You should see the "_View basic information about public channels in your workspace_", "_Send Message as ..._" and "_Send messages to channels ... isn't a member of_" as the permission, then click allow.
6. You can then see you token, in the form of `xoxb-...-...-...`
### Remark42 configuration
The slack token which you obtained before should be used as `NOTIFY_SLACK_TOKEN`.
You also need to set `NOTIFY_ADMINS=slack` for the Slack notification to be active.
By default, the notification are sent to the `general` channel on slack. If you need another channel, you can specify it, for instance with `NOTIFY_SLACK_CHAN=random`.
```
- NOTIFY_ADMINS=slack
- NOTIFY_SLACK_CHAN=general
- NOTIFY_SLACK_TOKEN=xoxb-....
```
### Verify the notifications on Slack
If all goes fine, you should be able to see the following message on your Slack notification channel:
> New comment from _author_ -> _original author_
>> [Demo | Remark42](http://127.0.0.1:8080/web/#remark42__comment-11288987987)
>> This is the comment written by _author_
## Telegram
### Telegram notifications for administrators
In order to integrate notifications about any comment on your sites with remark42 with [telegram](https://telegram.org)
1. Set `NOTIFY_ADMINS=telegram`
1. Make [a channel](https://telegram.org/faq_channels) and add it to remark42 configuration as `NOTIFY_TELEGRAM_CHAN`
1. Get a token according to the instruction below and add it to the configuration as well
### Getting token for Telegram
In order to get token "just talk to [BotFather](https://core.telegram.org/bots#6-botfather)". All you need is to send `/newbot` command, and choose the name for your bot (it must end in `bot`). This is it, you got a token which you'll need to write down into remark42 configuration as `TELEGRAM_TOKEN`.
_Example of such a "talk":_
```
Umputun:
/newbot
BotFather:
Alright, a new bot. How are we going to call it? Please choose a name for your bot.
Umputun:
example_comments
BotFather:
Good. Now let's choose a username for your bot. It must end in `bot`. Like this, for example: TetrisBot or tetris_bot.
Umputun:
example_comments_bot
BotFather:
Done! Congratulations on your new bot. You will find it at t.me/example_comments_bot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. By the way, when you've finished creating your cool bot, ping our Bot Support if you want a better username for it. Just make sure the bot is fully operational before you do this.
Use this token to access the HTTP API:
12345678:xy778Iltzsdr45tg
For a description of the Bot API, see this page: https://core.telegram.org/bots/api
```
@@ -1,10 +1,12 @@
---
title: Reproxy
parent: Configuration
order: 600
---
## How to configure remark42 with [Reproxy](https://reproxy.io)
Example of Reproxy configuration (reverse proxy) running remark42 service on remark42.example.com with docker compose. Reproxy handles SSL termination with LE and gzip all the responses.
Example of Reproxy configuration (reverse proxy) running remark42 service on remark42.example.com with docker compose. Reproxy handles SSL termination with LE and gzip all the responses.
```yaml
version: "3.4"
@@ -83,5 +85,4 @@ services:
reproxy.route: '^/(.*)'
reproxy.dest: '/$$1'
reproxy.ping: '/ping'
```
@@ -4,3 +4,77 @@ menuTitle: Subdomain
parent: Configuration
order: 600
---
## How to configure remark42 without a subdomain
All README examples show configurations with remark42 on its own subdomain, i.e. `https://remark42.example.com`. However, it is possible and sometimes desirable to run remark42 without a subdomain, but just under some path, i.e. `https://example.com/remark42`.
- The frontend URL looks like this: `s.src = 'https://example.com/remark42/web/embed.js;`
- The backend `REMARK_URL` parameter will be `https://example.com/remark42`
- And you also need to slightly modify the callback URL for the social media login API's:
- Facebook Valid OAuth Redirect URIs: `https://example.com/remark42/auth/facebook/callback`
- Google Authorized redirect URIs: `https://example.com/remark42/auth/google/callback`
- GitHub Authorised callback URL: `https://example.com/remark42/auth/github/callback`
### docker-compose configuration
Both Nginx and Caddy configuration below relies on remark42 available on hostname `remark42`, which is achieved by having `container_name: remark42` in docker-compose.
Example `docker-compose.yaml`:
```yaml
version: '2'
services:
remark42:
image: umputun/remark42:latest
container_name: remark42
restart: always
environment:
- REMARK_URL=https://example.com/remark42/
- SITE=<site_ID>
- SECRET=<secret>
- ADMIN_SHARED_ID=<shared_id>
volumes:
- ./data:/srv/var
logging:
options:
max-size: '10m'
max-file: '1'
```
### Nginx configuration
The `nginx.conf` would then look something like:
```
location /remark42/ {
rewrite /remark42/(.*) /$1 break;
proxy_pass http://remark42:8080/; // use internal docker name of remark42 container for proxy
proxy_set_header Host $http_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;
}
```
### Caddy configuration
Example of Caddy configuration (`Caddyfile`) running remark42 service on `example.com/remark42/`:
```
example.com {
gzip
tls mail@example.com
root /srv/www
log /logs/access.log
# remark42
proxy /remark42/ http://remark42:8080/ {
without /remark42
transparent
}
}
```
@@ -4,3 +4,58 @@ menuTitle: Translations
parent: Contributing
order: 300
---
## How to add new language translation to Remark42
Translation files are stored in [/frontend/app/locales](https://github.com/umputun/remark42/tree/master/frontend/app/locales)
directory with `.json` extension and content like following:
```json
{
"anonymousLoginForm.length-limit": "Username must be at least 3 characters long",
"anonymousLoginForm.log-in": "Log in",
"anonymousLoginForm.symbol-limit": "Username must start from the letter and contain only latin letters, numbers, underscores, and spaces",
<...>
}
```
### How to add a new translation
We truly appreciate people spending time contributing their translations to remark42. Please go through the steps
below in order to have your translation start being available to all remark42 users and included in the next release.
1. create a fork of [umputun/remark42](https://github.com/umputun/remark42) repo, and if you already have one please
pull the latest changes from the upstream master branch. It could be done like that:
```shell
git remote add upstream https://github.com/umputun/remark42.git
git fetch upstream
git rebase upstream/master
git push
```
1. add a new locale with [two-letter code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
of the language you want to make the translation into to list in
[frontend/tasks/supportedLocales.json](https://github.com/umputun/remark42/blob/master/frontend/tasks/supportedLocales.json)
1. run `npm install` in `frontend` folder
1. run `npm run translation:extract` in `frontend` folder
1. run `npm run translation:generate` in `frontend` folder
1. translate all values in the newly created json file in
[frontend/app/locales/](https://github.com/umputun/remark42/blob/master/frontend/app/locales/)
1. commit all changes above in your fork
1. test your changes in the interface:
1. uncomment `locale: "ru"` line in [frontend/index.ejs](https://github.com/umputun/remark42/blob/master/frontend/index.ejs#L133)
and replace `ru` with your translation language code
1. [run remark42 in Docker](https://github.com/umputun/remark42#development) by issuing following commands
from the root directory of your remark42 fork:
```shell
docker-compose -f compose-dev-frontend.yml build
docker-compose -f compose-dev-frontend.yml up
```
1. open [http://127.0.0.1:8080/web](http://127.0.0.1:8080/web), log in, make a comment, make a reply to a comment,
and make sure your translation looks as you expect it to look
1. make a screenshot from [http://127.0.0.1:8080](http://127.0.0.1:8080) with your translation in place
1. after all previous steps are done, create a [Pull Request](https://github.com/umputun/remark42/pulls) to umputun/remark42
repo with your changes, attaching a screenshot or two from your local test instance to it
@@ -69,4 +69,4 @@ Put the next code snippet on a page of your site where you want to have comments
After that widget will be rendered inside this node.
If you want to set this up on a Single Page App, see [appropriate doc page](https://github.com/umputun/remark42/blob/master/docs/spa.md).
If you want to set this up on a Single Page App, see [appropriate doc page](https://github.com/umputun/remark42/blob/master/site/src/docs/configuration/frontend/index.md).