EVOTk

[TUTO] Installation de Jellyfin en Docker ( HTTPS / Transcodage HW actifs )

Recommended Posts

 Installation de Jellyfin en Docker ( HTTPS / Transcodage HW actifs )

 

 

Note : Afin de ne pas avoir a maintenir plusieurs tuto a différents endroit, retrouvez ce tuto mis a jour en cliquant ici !

 

 

 

Bonjour,

Topic en cours de rédaction 😘 Je suis encore en phase de test, toute aide, commentaires, ... et la bienvenue afin de rendre ce topic le plus complet possible.

 

Jellyfin, c'est quoi ?

Jellyfin est un programme gratuit qui vous permet de collecter, contrôler et diffuser tous vos médias préférés. C'est un programme simillaire a Plex, et c'est un fork a Emby. Ceelui-ci a l'avantage d'être 100% libre ( comme le fût Emby au départ ). D'ailleurs Jellyfin est basé sur la derniere version libre de Emby ( c'est pour cela que c'est un "fork" d'Emby ). Contrairement a Plex ou Emby, aucune fonction n'est payante, comme le transcodage hardware ou l'acces au application mobile.

 

Sommaire :

1/ Connaître le PUID et PGID d'un utilisateur

2/ Créer les dossiers nécessaires

3/

4/ Création du fichier "docker-compose.yml"

5/ Création des conteneurs avec docker-compose

6/ Configuration du Reverse Proxy dans DSM

7/ Accès a Jellyfin, 1ere configuration

 

Pré-requis : 

Avoir installé le paquet Docker

Utiliser le Loader 918+

Avoir un accès SSH au Syno/Xpenology

Dans docker : télécharger l'image jellyfin/jellyfin:latest et nginxinc/nginx-unprivileged:alpine

Posséder un nom de domaine

 

Nous allons ici utiliser docker-compose, cette solution ne pourra donc ce faire, uniquement sur un NAS ou est possible d'installer Docker.

 

Le but de ce tuto sera de rendre cette installation facile et accessible a tous, bien que loin d’être un expert de docker/docker-compose, n’hésiter pas à répondre à ce sujet avec vos interrogations, ..

Pour ceux qui sont plus alèze avec ce genre d'installation, n'hésiter pas a proposer des améliorations, ou des conseils, ...

 

 

1/ Connaitre le PUID et PGID d'un utilisateur

 

2/ Créer les dossiers/fichiers nécessaires

 

Les chemins sont basé sur mon installation, à adapter selon votre installation.

Voici les dossiers a créer :

- /volume1/docker/jellyfin/config

- /volume1/docker/jellyfin/cache

 

Et la configuration du ngnix, à enregistrer dans un fichier "jellyfin_nginx.conf", à placer par ma config dans "/volume1/docker/jellyfin" :

Citation

server {
  listen 8080;
  server_name _;
 
    location / {
        # Proxy main Jellyfin traffic
        proxy_pass http://jellyfin:8096;
        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 X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;

        # Disable buffering when the nginx proxy gets very resource heavy upon streaming
        proxy_buffering off;
    }
    location /socket {
        # Proxy Jellyfin Websockets traffic
        proxy_pass http://jellyfin:8096;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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 X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
    }
}

 

4/ Création des conteneurs avec docker-compose

Nous allons maintenant créer un fichier "docker-compose.yml" avec les paramètres des conteneurs.

Voici mon fichier "docker-compose.yml" :

Citation

version: "3"

services:
  jellyfin:
    image: jellyfin/jellyfin:latest
    container_name: jellyfin
    restart: unless-stopped
    environment:
     - PUID=XXXX
     - PGID=XXXX
     - TZ=Europe/Paris
    devices:
      - /dev/dri/renderD128:/dev/dri/renderD128
    sysctls:
      - net.ipv6.conf.all.disable_ipv6=0
    networks:
      - jellyfin
    ports:
      - 8096:8096
    expose:
      - 8096
    volumes:
      - /volume1/docker/jellyfin/config:/config
      - /volume1/docker/jellyfin/cache:/cache
 

  nginx:
    image: nginxinc/nginx-unprivileged:alpine
    container_name: jellyfin_proxy
    restart: unless-stopped
    networks:
      - jellyfin
    volumes:
      - /volume1/docker/jellyfin/jellyfin_nginx.conf:/etc/nginx/conf.d/default.conf:ro
    ports:
      - "8083:8080"

 

networks:
  jellyfin:
    external:
      name: jellyfin

 

On peut y voir 2 services "jellyfin" et "jellyfin_proxy".

 

Dans le service "jellyfin" vous allez devoir porter votre attention sur :

- PUID=XXXX, à modifier avec le PUID de votre utilisateur
- PGID=XXXX, à modifier avec le PUID de votre utilisateur

- /volume1/docker/jellyfin/config

- /volume1/docker/jellyfin/cache

la 1ere partie "/volume1/docker/vpn/config" et  "/volume1/docker/vpn/config" correspondent aux chemins vers les dossiers précédemment créer, qui contiendrons votre installation Jellyfin.

 

Dans le service "jellyfin_proxy", vous allez devoir porter votre attention sur :

- /volume1/docker/jellyfin/jellyfin_nginx.conf:/etc/nginx/conf.d/default.conf:ro, la 1ere partie "/volume1/docker/jellyfin/jellyfin_nginx.conf" correspond au chemin vers le fichier de configuration du proxy

 

Une fois les modifications effectuées, enregistrer votre fichier sous le nom : docker-compose.yml

Puis charger le fichier sur votre NAS ( chez moi, il se trouve dans /volume1/docker/jellyfin )

 

5/ Création des conteneurs avec docker-compose

 

En SSH, 1ere chose, je passe en mode administrateur avec la commande :

Citation

sudo su -

Le mot de passe admin vous est demandé.

 

Dans mon dossier /volume1/docker/jellyfin , j'ai chargé mon fichier docker-compose.yml. Je vais donc accéder à ce dossier, pour cela je fait :

Citation

cd /volume1/docker/jellyfin

 

Ensuite, afin "d’exécuter" mon fichier docker-compose.yml, je tape en ssh :

Citation

sudo docker-compose up -d

 

La création des conteneurs se fait, ils deviennent visible dans l'appli "Docker" de DSM. Si tout se passe bien, ils doivent apparaître démarrer dans Docker.

 

6/ Configuration du Reverse Proxy dans DSM

X

 

7/ Accès a Jellyfin, 1ere configuration

X

Edited by EVOTk
  • Like 3

Share this post


Link to post
Share on other sites

Merci encore pour cette contribution :) Je ne savais pas qu'il existait en quelque sorte une version libre de Plex.

J'ai testé rapidement et la config se fait assez simplement, seul l'interface n'est pas encore aussi aboutie que Plex mais c'est clairement en bonne voie. Par contre pour l'application mobile sur iOS les commentaires ne sont pas élogieux, mieux vaut rester sur la vesrion Web full gratuite.

Share this post


Link to post
Share on other sites

Merci pour le tuto, je n'avais même pas pensé à nginx pour l'accès extérieur, j'ai trouvé plus simple de créer des sous-domaines dédiés à Plex et Jellifin et d'utiliser le reverse proxy intégré à DSM dans "Panneau de configuration/Portail des applications/Proxy inversé". Du coup, un même certificat Let's Encrypt couvre mon domaine ainsi que plusieurs sous-domaines dédiés chacun à une fonction précise et je peux me connecter en SSL sans soucis.

Quelle serait la solution la plus propre et y a t-il un inconvénient à ma méthode?

Concernant Jellyfin, arrives-tu à transcoder en hardware du HEVC 10 bits? J'attends désespérément la nouvelle version qui devrait corriger ce soucis mais elle tarde à arriver, le correctif a bien été porté sur la master mais ils ne font pas de nightly en docker... Sans compter l'affichage des sous-titres assez médiocre sur boite noire transparente, il y a encore du boulot.
Pour le moment, je reste avec Plex qui transcode parfaitement en hard à l'intérieur comme à l'extérieur de mon domicile, sans compter la présentation en infinite scrolling que je préfère aux pages d'emby ou Jellyfin, mais je suis la progression de ce soft et installe chaque nouvelle version en espérant du mieux... Mais depuis la 1.3.7, c'est plutôt un enchainement de régressions, dommage

Edited by pmchan

Share this post


Link to post
Share on other sites
Il y a 7 heures, nicoueron a dit :

Merci encore pour cette contribution :) Je ne savais pas qu'il existait en quelque sorte une version libre de Plex.

J'ai testé rapidement et la config se fait assez simplement, seul l'interface n'est pas encore aussi aboutie que Plex mais c'est clairement en bonne voie. Par contre pour l'application mobile sur iOS les commentaires ne sont pas élogieux, mieux vaut rester sur la vesrion Web full gratuite.

 

Clairement Jellyfin n'est pas pres a remplacé mon Plex également :) mais c'est deja fonctionnel et cela avance ! Et clairement je trouve que Plex à en dernier c'est beaucoup écarté de son but principal ! A voir par la suite ...

L'application mobile sur Android a des petits bugs également ( par exemple chez moi l'affichage des musiques ), je préfère la version web.

 

 

Il y a 7 heures, pmchan a dit :

Merci pour le tuto, je n'avais même pas pensé à nginx pour l'accès extérieur, j'ai trouvé plus simple de créer des sous-domaines dédiés à Plex et Jellifin et d'utiliser le reverse proxy intégré à DSM dans "Panneau de configuration/Portail des applications/Proxy inversé". Du coup, un même certificat Let's Encrypt couvre mon domaine ainsi que plusieurs sous-domaines dédiés chacun à une fonction précise et je peux me connecter en SSL sans soucis.

Quelle serait la solution la plus propre et y a t-il un inconvénient à ma méthode?

 

Je n'est pas réussi a faire ceci correctement, donc au final, en plus d'utiliser le proxy inversé de DSM, j'utilise le conteneur Ngnix.

Mise en place avec cette aide : https://jellyfin.org/docs/general/administration/reverse-proxy.html#nginx

 

Il y a 7 heures, pmchan a dit :

Concernant Jellyfin, arrives-tu à transcoder en hardware du HEVC 10 bits? J'attends désespérément la nouvelle version qui devrait corriger ce soucis mais elle tarde à arriver, le correctif a bien été porté sur la master mais ils ne font pas de nightly en docker... Sans compter l'affichage des sous-titres assez médiocre sur boite noire transparente, il y a encore du boulot.

Pour le moment, je reste avec Plex qui transcode parfaitement en hard à l'intérieur comme à l'extérieur de mon domicile, sans compter la présentation en infinite scrolling que je préfère aux pages d'emby ou Jellyfin, mais je suis la progression de ce soft et installe chaque nouvelle version en espérant du mieux... Mais depuis la 1.3.7, c'est plutôt un enchainement de régressions, dommage

 

J'ai principalement des fichiers en H264, je vais regarder si je trouve du HEVC 10bits ( ou MP moi avec un lien/torrent si tu as un fichier spécifique que tu aimerai que je test ).

Pour le moment je reste sur Plex également, il faut avouer que cela marche bien ;) Sur Jellyfin contrairement a Plex, pas de possibilité d'avoir un tampon pour le transcodage, sur Plex, une fois que le transcodage a ateint le tampon, il réduit sa charge, et transcode tranquillement, sur Jellyfin, il transcode a fond jusqu’à la fin du fichier. J'ai meme fait une demande de fonctionnalité, https://features.jellyfin.org/posts/391/transcoding-buffer a voir ;)

 

@pmchan Je viens d'essayer avec un fichier HEVC Main 10, j'ai une erreur "PlaybackErrorNoCompatibleStream". 😓

Edited by EVOTk

Share this post


Link to post
Share on other sites

Oui, voilà, il y a un soucis depuis la 10.3.7 qui a été résolu par un certain cryptobank sur le github officiel. Sa correction a été portée sur la master et devrait donc se trouver dans la future 10.4.4.
Pour tester la lecture de différents codec, j'utilise les vidéos de test Jellyfish, elles sont variées et permettent de voir si le transcodage hardware se passe bien.

 

Concernant mes réglages reverse proxy dans DSM, voilà à quoi ils ressemblent pour accéder à Plex de l'extérieur, si ça peut aider.

Le numéro de port est un exemple mais je l'ai modifié par rapport aux défauts 5000/5001, toutes mes connexions aux différents services du NAS transitent donc par cet unique port qui est le seul forwardé par le routeur vers lui (ainsi que les port 80 et 443 pour Let's Encrypt).

 

Le nom de domaine principal me sert pour un site web, j'ai donc créé autant de sous-domaines que nécessaires ce qui me donne par exemple:
https://syno.mondomaine.com:1823 pour accéder à DSM,  https://plex4g.mondomaine.com:1823 pour Plex, etc...

 

 

Capture d’écran 2020-01-14 à 10.48.42.png

Edited by pmchan

Share this post


Link to post
Share on other sites

Je suis en train de mettre le mettre en place.

 

pourquoi mettre en place le reverse proxy nginx en plus de celui de DSM ?

Share this post


Link to post
Share on other sites
Posted (edited)
il y a 40 minutes, nicoueron a dit :

pourquoi mettre en place le reverse proxy nginx en plus de celui de DSM ?

 

Le proxy ngnix sert pour la connexion chiffré, celui de dsm pour la génération et la mise en place du certificat ( en gros ^^ )

 

Si tu te sert uniquement du DSM, il manquerai des paramètres pour les websockets, si tu te sert que du ngnix il te faudrait générer toi même les renouvellements de certificats

Edited by EVOTk

Share this post


Link to post
Share on other sites

Pas sur de comprendre.

Entre le nginx de DSM (celui de base) qui chiffre entre le navigateur et DSM OK. Mais entre DSM et le conteneur Jellyfin par défaut y a rien OK, mais honnêtement on est en réseau local et je crois que Jellyfin permet naturellement de porter lui aussi un certificat pour combler ce manque.

 

Don je ne vois pas l'intérêt.

 

C'est ce que j'ai fait et ça marche très bien aux 2 headers pour les websockets (classique j'ai envie de dire).

Share this post


Link to post
Share on other sites

Je ferai aussi qq remarques supplémentaires :

  •  il manque la création du réseau jellyfin au préalable
docker network create jellyfin
  • Le répertoire cache ne sert à rien, il se trouve directement dans /config/cache. Pour preuve chez moi config est tout le vide
  • Pour le transcodage hard, je suppose que tu mets /dev/dri/renderD128 parce que tu as un GPU. Pour ceux qui n'en n'ont pas il ne faut pas mettre cette ligne.

A près s'il s'avère que ce j'ai dit plus haut est vrai sur le nginx alors toute la partie sur docker-compose ne sert à rien non plus car on peut tout faire depuis l'application Docker de DSM.

 

Enfin pour conclure, l'outil est pas mal mais je trouve que l'affichage d'un bibliothèque est considérablement lent chez moi. Le chargement des miniatures prend un temps de dingue comparer à Plex. Pour le chargement de 100 affiches de films, cela me prend 1 min!

 

Perso, voici mon docker-compose.yaml pour mon N54L :

version: "3"

services:
  jellyfin:
    image: linuxserver/jellyfin:latest
    container_name: jellyfin
    restart: unless-stopped
    environment:
     - PUID=1032
     - PGID=100
     - TZ=Europe/Paris
    sysctls:
      - net.ipv6.conf.all.disable_ipv6=0
    networks:
      - jellyfin
    ports:
      - 8096:8096
    expose:
      - 8096
    volumes:
      - /volume1/docker/jellyfin/config:/config
      - /volume1/video/Films:/films
      - /volume1/photo:/photo
      - /volume1/music:/music

networks:
  jellyfin:
    external:
      name: jellyfin

 

Share this post


Link to post
Share on other sites
il y a 41 minutes, nicoueron a dit :

Pas sur de comprendre.

Entre le nginx de DSM (celui de base) qui chiffre entre le navigateur et DSM OK. Mais entre DSM et le conteneur Jellyfin par défaut y a rien OK, mais honnêtement on est en réseau local et je crois que Jellyfin permet naturellement de porter lui aussi un certificat pour combler ce manque.

 

Effectivement, en local, aucun intérêt.

il y a 31 minutes, nicoueron a dit :

il manque la création du réseau jellyfin au préalable


docker network create jellyfin

 

 

Effectivement, il faut que je l'intègre au tuto, merci

 

il y a 31 minutes, nicoueron a dit :

Le répertoire cache ne sert à rien, il se trouve directement dans /config/cache. Pour preuve chez moi config est tout le vide

 

Dans la procédure officielle, il est demandé de faire une dossier /cache, voici pourquoi il est présent dans mon docker-compose.

 

il y a 31 minutes, nicoueron a dit :

Pour le transcodage hard, je suppose que tu mets /dev/dri/renderD128 parce que tu as un GPU. Pour ceux qui n'en n'ont pas il ne faut pas mettre cette ligne.

 

Effectivement, je préciserai, le tuto est basé sur ma config et ne s’adapte pas forcément à toutes les configurations.

 

il y a 38 minutes, nicoueron a dit :

A près s'il s'avère que ce j'ai dit plus haut est vrai sur le nginx alors toute la partie sur docker-compose ne sert à rien non plus car on peut tout faire depuis l'application Docker de DSM.

 

Même avec la partie ngnix, tout est faisable depuis l'application Docker. J'utilise docker-compose par simplicité ( pour moi ), mais dans ce tuto on peut très bien ne pas l'utiliser du début, a la fin.

 

il y a 41 minutes, nicoueron a dit :

Enfin pour conclure, l'outil est pas mal mais je trouve que l'affichage d'un bibliothèque est considérablement lent chez moi. Le chargement des miniatures prend un temps de dingue comparer à Plex. Pour le chargement de 100 affiches de films, cela me prend 1 min!

 

Chez moi, je n'ai pas de soucis, je le trouve Jellyfin réactif, l'indexation est rapide ( plus que plex je trouve ), par contre l’association des films, .. et meilleur sur Plex pour le moment.

Apres c'est difficilement comparable, nous n'avons pas les mêmes configs. L'affiche /100 est relou, je trouve, je préfère Plex avec son scroll "infini".

  • Like 1

Share this post


Link to post
Share on other sites
il y a 2 minutes, EVOTk a dit :

Apres c'est difficilement comparable, nous n'avons pas les mêmes configs. L'affiche /100 est relou, je trouve, je préfère Plex avec son scroll "infini".

Moi aussi. Plex est beaucoup plus mature. Mais le fait qu'ils ont stoppé le support des plugin est pour moi une grave erreur stratégique même si je comprend un peu ce choix.

Share this post


Link to post
Share on other sites

Petite précision au sujet du dossier cache, il semble que dans l'image officielle il soit "externe" au dossier config (comme tu le suggères) alors qu'avec l'image linuxserver le dossier cache est nativement à l'intérieur de config. Pour ton cas, ce n'est pas donc pas nécessaire de sortir le dossier cache si tu utilises l'image linuxserver.

 

Perso, après avoir testé l'image linuxserver qui je trouve rame et consomme beaucoup de RAM (environ 2Go!)  Je suis en train de tester l'image officielle. Je te ferai un retour pour voir s'il y a une différence

Share this post


Link to post
Share on other sites
il y a 21 minutes, nicoueron a dit :

Petite précision au sujet du dossier cache, il semble que dans l'image officielle il soit "externe" au dossier config (comme tu le suggères) alors qu'avec l'image linuxserver le dossier cache est nativement à l'intérieur de config. Pour ton cas, ce n'est pas donc pas nécessaire de sortir le dossier cache si tu utilises l'image linuxserver.

 

Perso, après avoir testé l'image linuxserver qui je trouve rame et consomme beaucoup de RAM (environ 2Go!)  Je suis en train de tester l'image officielle. Je te ferai un retour pour voir s'il y a une différence

 

Merci de ton retour.

Ton Jellyfin n'est pas entrain de bosser ? Chez moi au repos 70Mo de RAM d'apres Docker, contre 310Mo pour plex.

Share this post


Link to post
Share on other sites
Il y a 16 heures, EVOTk a dit :

Ton Jellyfin n'est pas entrain de bosser ?

Non il en fait plus rien.

 

Là avec l'image officielle j'ai le même comportement. Des lenteurs pas possible dans les menus pour afficher les images et une consommation mémoire proche du 1Go pour.... rien faire 😕

image.thumb.png.00af34a02fa174285863cce7dd2521d5.png

 

Après j'ai une N54L... possible que ça ne soit pas suffisant. 

Finalement je crois que je vais rester sur Plex et laisser Jellyfin seulement pour la TV ;)

Share this post


Link to post
Share on other sites

Effectivement, tres étrange. Mais des fois je doute de la véracité des infos de Docker !

rmJgfWb.png

Share this post


Link to post
Share on other sites

image.thumb.png.b77eb34b4e46bcbc61418fce78ba71de.png

je pense que je suis pas mal là !

 

 

Pour ce qui est de la lenteur dans les menus je pense avoir compris le pb. En fait c'est bien lié à l'implémentation de Jellyfin.  Je m'explique. Les vignettes dans le Plex pèsent environ 10ko alors que les mêmes dans Jellyfin pèse entre 80 et 100ko... Avec ma ligne VDSL de 5Mbits montant le constat est là! C'est dommage de mettre des vignettes trop grandes.

  • Like 1

Share this post


Link to post
Share on other sites

Pour info, j'ai eu aussi ce message d'erreur :

Error in Directory watcher for: "/media/movies" System.IO.IOException: The configured user limit (8192) on the number of inotify watches has been reached.

Message mentionné dans la doc Dellyjin https://jellyfin.org/docs/general/administration/troubleshooting.html

 

Pour ne plus l'avoir j'ai fait comme indiqué dans leur doc (au niveau de DSM) 

$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
$ sudo sysctl -p

Et depuis plus de message d'erreur!

Share this post


Link to post
Share on other sites

Salut,

J'ai eu le même chose avec Plex. Par contre, cela m’étonne que tu ne doit pas le faire dans le conteneur docker mais dans DSM 🤨

Share this post


Link to post
Share on other sites
Il y a 21 heures, EVOTk a dit :

Salut,

J'ai eu le même chose avec Plex. Par contre, cela m’étonne que tu ne doit pas le faire dans le conteneur docker mais dans DSM 🤨

pourtant c'est bien ce que j'ai fait. L'autorisation doit êter accordé à l'hôte et non le conteneur (c'est d'ailleurs Jellyfin qui le dit)

Share this post


Link to post
Share on other sites

C'est possible d'activer le transcodage avec la puce graphique du processeur ? 

J'ai un I3-4130 et quand je lance un film en transcode le CPU est proche des 100% J'aurais aimé le soulager un peux.

 

Share this post


Link to post
Share on other sites

Salut,

Le tuto comprend l'activation du transcodage hard pour jellyfin mais comme l'indique le message en tete du tuto, la version a jour est ici : https://www.forum-nas.fr/viewtopic.php?f=56&t=13215

 

C'est plus simple pour moi de n'avoir que un "post" a tenir a jour.

Bien évidemment, il faut que le transcodage hard soit activé sur ton DSM pour que cela fonctionne.

Share this post


Link to post
Share on other sites

Justement. Comment activer le transcodage sur dsm ? J'ai trouvé deux trois trucs sur la toile mais rien de parlant. 

 

J'ai mis mon xpenology en ds3615xs 

Share this post


Link to post
Share on other sites
il y a une heure, cmathias a dit :

Justement. Comment activer le transcodage sur dsm ? J'ai trouvé deux trois trucs sur la toile mais rien de parlant. 

 

J'ai mis mon xpenology en ds3615xs 

Il faut utiliser le loader pour DSM 918+
Avoir un numéro de série valide ou utiliser cette technique : https://xpenology.com/forum/topic/24864-transcoding-without-a-valid-serial-number/?tab=comments#comment-132328

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.