4 - Technical documentation

Configuring tools for internal use

Configuring tools for internal use


Install and configuration of Weblate

Docker install

Following steps in:


Steps done:

```sudo adduser weblate --home /var/www/weblate.co.tools sudo su weblate sudo mkdir /var/www/weblate.co.tools cd /var/www/weblate.co.tools git clone https://github.com/WeblateOrg/docker-compose.git weblate-docker cd weblate-docker

echo "version: '2' services: weblate: environment:

  - WEBLATE_EMAIL_HOST=smtp.co.tools
  - WEBLATE_SERVER_EMAIL=wave@communecter.org
  - WEBLATE_DEFAULT_FROM_EMAIL=wave@communecter.org
  - WEBLATE_ALLOWED_HOSTS=weblate.co.tools,localhost
  - WEBLATE_SITE_TITLE=Plateforme de traduction de Communecter
  - WEBLATE_ADMIN_EMAIL=wave@communecter.org
  - WEBLATE_ADMIN_NAME="Administrateur"
  - WEBLATE_SOCIAL_AUTH_GITLAB_API_URL=https://weblate.co.tools/accounts/complete/gitlab/

" > docker-compose.override.yml

With values according to mail server.

And finally:

```sudo docker-compose up

Configure apache : /etc/apache2/sites-enabled/weblate.co.tools.conf :

<VirtualHost *:80>
        ServerName weblate.co.tools
        ServerAdmin webmaster@make.social

        ProxyPass / http://localhost:10080/
        ProxyPassReverse / http://localhost:10080/
        ProxyRequests Off
        ProxyPreserveHost On

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

Configure lets encrypt :

certbot --apache -d weblate.co.tools

Et on repasse sur les fichiers de conf Apache weblate.co.tools-le-ssl.conf :

<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerName weblate.co.tools
        ServerAdmin webmaster@make.social

        ProxyPass / http://localhost:10080/
        ProxyPassReverse / http://localhost:10080/
        ProxyRequests Off
        ProxyPreserveHost On

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        RequestHeader set X-Forwarded-Proto "https"

SSLCertificateFile /etc/letsencrypt/live/weblate.co.tools/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/weblate.co.tools/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf

Ainsi que : weblate.co.tools.conf

<VirtualHost *:80>
        ServerName weblate.co.tools
        ServerAdmin webmaster@make.social

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        Redirect permanent / https://weblate.co.tools/

Weblate configuration (pixel-humain project)

In weblate, a project is made of components. Each component has one translation file per language. If your source code uses many files for a given language, you will have to create a new component for each file.

Hopefully, weblate has a Component discovery addon. Using this addon, Weblate automatically discovers sources files for a given language. To use this addon, you have to :

Gitlab configuration (co2-bot)

In weblate, when creating a new project, you have to create a first component to set the repository of the source code. You have to use two URLs : the source code repository, and the push repository. Select the main repository as the Source code Repository, and the fork repository as the Push URL.

On Gitlab :

  1. the weblate user is co2-bot. To use Weblate properly on Gitlab, you should fork the repo you want to integrate to Weblate using co2-bot user. For example co2-bot forked pixel-humain.
  2. set a webhook in the main repository to the weblate URL : https://weblate.co.tools/hooks/gitlab/

The workflow should be like below :

  1. As Developers, you will have to initialize empty translation files (with keys but no values). When you push to the source code repository, weblate will automatically pull the new files and update the translations accordingly.
  2. As Translators, you work on the translations. When you are ready, you can push to the push repository using Weblate interface.
  3. As Developers or Translators, when you have a major release, you should create a Merge Request between co2-bot fork repository and the main repository. Check the consistency of the files and do a squashed merge once you are ready.
Configuring tools for internal use

Ubuntu server

Installing and configuring the Ubuntu server 16.04

Define a password for root user

ubuntu is the root user. The password can be useful in case SSH doesn't work any more, for recovery with VNC.

sudo su
passwd ubuntu

Mount the 2nd hard drive in /var/www

sudo mkfs.xfs -f /dev/vdb
sudo mkdir /var/www
sudo mount /dev/vdb /var/www
sudo blkid
sudo nano /etc/fstab

Remplacer l'UUID par celui donné par blkid pour /dev/sdb

LABEL=cloudimg-rootfs   /        ext4   defaults        0 0
UUID=4a4004ff-9191-432c-8693-75dbf533f061    /var/www           xfs    defaults        0       2

Set Time zone

dpkg-reconfigure tzdata
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -uroot mysql -p
mysql -u root -p
SET GLOBAL time_zone = "Europe/Paris";

And restart the system or just MySQL : service mysql reload

Set Locale

sudo /usr/share/locales/install-language-pack fr_FR



sudo ufw allow OpenSSH
sudo ufw deny 21
sudo ufw enable
sudo ufw status


Newest version : https://github.com/ossec/ossec-hids/ (Server/Agent Unix)

sudo su
apt install build-essential inotify-tools sendmail

if stops at ``

pidof apt
kill xxxx
cd /etc/mail/tls
sudo openssl dsaparam -out sendmail-common.prm 2048
sudo chown root:smmsp sendmail-common.prm
sudo chmod 0640 sendmail-common.prm
sudo dpkg --configure -a
wget https://github.com/ossec/ossec-hids/archive/2.9.0.tar.gz
tar xzvf 2.9.0.tar.gz
cd ossec-hids-2.9.0

choose local (not server) enter email choose default for all others options

nano /var/ossec/etc/ossec.conf add :


And check email_to and email_from

nano /var/ossec/rules/local_rules.xml add :

<rule id="100013" level="0">
    <description>Ignoring phpMyAdmin events.</description>

<rule id="100014" level="0">
        <description>Ignoring Humhub Polls module activation events, phpMyAdmin, HackMd (socket.io), Piwik and OnlyOffice.</description>

<rule id="100015" level="0">
    <description>Ignoring Humhub Ajax when disconnected</description>

Automaticaly add IP in white list


  1. create approved_humhub_list and chmod 666 in order to apache to be able to edit this file :
    echo "" >/var/ossec/lists/approved_humhub_list
    chmod 666 /var/ossec/lists/approved_humhub_list
  2. edit nano /var/ossec/etc/ossec.conf and in <rules></rules> add:
  3. service ossec restart
  4. In /var/ossec/rules/local_rules.xml, add:
    <rule id="100016" level="0">
    <if_sid>31100, 31103, 31533</if_sid>
    <list field="srcip" lookup="address_match_key">lists/approved_humhub_list</list>
    <description>Quiet: Approved admin</description>
    id="100016" must be unique, change it if necessary !
  5. Update automaticaly /var/ossec/lists/approved_humhub_list.cdb every minutes adding this in root crontab: ```
          • /var/ossec/bin/ossec-makelists >/dev/null 2>&1 ```

Call this script in your website if current user is admin :

        $file = '/var/ossec/lists/approved_humhub_list';
        $ip = $_SERVER['REMOTE_ADDR'];
        $username = Yii::$app->user->identity->username;

        // read file
        $content = file_get_contents($file);

        // If user IP is not in white list
        if (!strpos($content, $ip)) {
            $lines = explode("\n", $content);

            // delete previous IPs corresponding to the current username
            foreach ($lines as $key => $line) {
                if (strpos($line, $username) || $line == '')
                    unset ($lines[$key]);

            // add new IP
            $lines[] = $ip.":".$username;

            // Update file
            file_put_contents($file, implode("\n", $lines));


Newest version : https://github.com/ossec/ossec-wui/releases

su web
cd /home/web/www
wget https://github.com/ossec/ossec-wui/archive/0.9.tar.gz
tar xzvf 0.9.tar.gz
rm 0.9.tar.gz
mv ossec-wui* ossec
cd ossec
sudo su

choose www-data

/etc/init.d/apache2 restart
/etc/init.d/ossec start


More details here


sudo su
apt install fail2ban
nano /etc/fail2ban/jail.conf
ignoreip = cramf.mooo.com
bantime  = 900
maxretry = 3


enabled = true
port    = ssh,sftp
filter  = sshd
logpath  = /var/log/auth.log
maxretry = 3

enabled = true
filter = apache-w00tw00t
action = iptables[name=Apache-w00tw00t,port=80,protocol=tcp]
logpath = /var/log/apache2/access*.log
maxretry = 1

enabled  = true  

enabled  = true 

enabled  = true
nano /etc/fail2ban/filter.d/apache-w00tw00t.conf

failregex = ^<HOST> -.*"GET \/w00tw00t\.at\.ISC\.SANS\.DFind\:\).*".*

ignoreregex =
fail2ban-client reload
fail2ban-client status


apt install apache2 libcgi-fast-perl libapache2-mod-fcgid
a2enmod fcgid


apt install munin munin-node munin-plugins-extra
chown -R munin:munin /var/cache/munin/www
nano /etc/munin/munin.conf

Uncomment :

dbdir /var/lib/munin
htmldir /var/cache/munin/www
logdir /var/log/munin
rundir /var/run/munin
contact.someuser.command mail -s "Munin notification"

And replace email address

nano /etc/munin/apache.conf

Replace :

        Order allow,deny
        Allow from localhost ::1
        Allow from all
        Options None

By :

        Require all granted
        Options FollowSymLinks SymLinksIfOwnerMatch
cd /etc/munin/plugins
sudo ln -s /usr/share/munin/plugins/mysql_
sudo ln -s /usr/share/munin/plugins/mysql_bytes
sudo ln -s /usr/share/munin/plugins/mysql_queries
sudo ln -s /usr/share/munin/plugins/mysql_slowqueries
sudo ln -s /usr/share/munin/plugins/mysql_threads
service munin-node restart
service apache2 reload

Go to http://IPAdress/munin If it doesn't work, create a Vhost in /etc/apache2/sites-available :

<VirtualHost *:80>
# Enable this for template generation
    ServerName munin.domain.ext

    ServerAdmin name@domain.ext
    DocumentRoot /var/cache/munin/www

# Enable this for cgi-based templates
#Alias /munin-cgi/static /var/cache/munin/www/static
#ScriptAlias /munin-cgi /usr/lib/munin/cgi/munin-cgi-html
#<Location /munin-cgi>
#    Order allow,deny
#    Allow from localhost ::1
#    AuthUserFile /etc/munin/munin-htpasswd
#    AuthName "Munin"
#    AuthType Basic
#    require valid-user

<Directory /var/cache/munin/www>
     Require all granted
     Options FollowSymLinks SymLinksIfOwnerMatch
    # This file can be used as a .htaccess file, or a part of your apache
    # config file.
    # For the .htaccess file option to work the munin www directory
    # (/var/cache/munin/www) must have "AllowOverride all" or something 
    # close to that set.

    # AuthUserFile /etc/munin/munin-htpasswd
    # AuthName "Munin"
    # AuthType Basic
    # require valid-user

    # This next part requires mod_expires to be enabled.

    # Set the default expiration time for files to 5 minutes 10 seconds from
    # their creation (modification) time.  There are probably new files by
    # that time. 

    <IfModule mod_expires.c>
        ExpiresActive On
        ExpiresDefault M310


# Enables fastcgi for munin-cgi-html if present
#<Location /munin-cgi>
#    <IfModule mod_fastcgi.c>
#        SetHandler fastcgi-script
#    </IfModule>

#<Location /munin-cgi/static>
#    SetHandler None

# Enables fastcgi for munin-cgi-graph if present
ScriptAlias /munin-cgi/munin-cgi-graph /usr/lib/munin/cgi/munin-cgi-graph
<Location /munin-cgi/munin-cgi-graph>
        Require all granted
    # AuthUserFile /etc/munin/munin-htpasswd
    # AuthName "Munin"
    # AuthType Basic
    # require valid-user
    <IfModule mod_fcgid.c>
        SetHandler fcgid-script
    <IfModule !mod_fcgid.c>
        SetHandler cgi-script

ScriptAlias /munin-cgi/munin-cgi-html /usr/lib/munin/cgi/munin-cgi-html
<Location /munin-cgi/munin-cgi-html>
        Require all granted
    # AuthUserFile /etc/munin/munin-htpasswd
    # AuthName "Munin"
    # AuthType Basic
    # require valid-user
    <IfModule mod_fcgid.c>
        SetHandler fcgid-script
    <IfModule !mod_fcgid.c>
        SetHandler cgi-script


sudo su
apt install monit
systemctl enable monit
nano /etc/monit/monitrc
set daemon 120
set mailserver localhost
set alert name@domain.ext only on { timeout, icmp }
set httpd port 2812 and
allow admin:monit # require user 'admin' with password 'monit'
systemctl restart monit
ufw allow 2812

Got to http://IpAdress:2812

user 'admin' / password 'monit'


Follow this documentation except the PHP paragraph

Install PHP7.1 (instead of 7.0 in Ubuntu 16.04)

sudo su
apt install -y python-software-properties
add-apt-repository ppa:ondrej/php
apt update
sudo apt-get install php7.1 libapache2-mod-php7.1 php7.1-mcrypt php7.1-mysql php7.1-bcmath php7.1-bz2 php7.1-ctype php7.1-curl php-date php7.1-dom php7.1-enchant php7.1-exif php7.1-fileinfo php7.1-ftp php7.1-gd php7.1-gettext php7.1-iconv php7.1-imagick php7.1-imap php7.1-mongodb php7.1-dev php7.1-intl php7.1-json php7.1-mbstring php7.1-mcrypt php7.1-memcache php7.1-memcached php7.1-mysql php7.1-mysqli php7.1-mysqlnd php7.1-pgsql php7.1-posix php7.1-redis php7.1-sockets php7.1-sqlite3 php7.1-tokenizer php7.1-wddx php7.1-xml php7.1-xmlreader php7.1-xmlrpc php7.1-xmlwriter php7.1-xsl php7.1-zip php7.1-ldap php7.1-apcu git curl zip unzip imagemagick
a2enmod 7.1
update-alternatives --config php

Select 7.1 version

List enabled apache2 modules : apachectl -t -D DUMP_MODULES Enable URL rewriting module : a2enmod rewrite

nano /etc/php/7.1/apache2/php.ini :

post_max_size = 20M
upload_max_filesize = 20M
max_file_uploads = 50
max_input_time = 180
memory_limit = 256M
date.timezone = Europe/Paris

sudo nano /etc/apache2/apache2.conf (replace xxx.xxx.xxx.xxx by IP server address) : Add to the end of the file : ServerName xxx.xxx.xxx.xxx

service apache2 reload

A bug can make Apache crash. Workaround : nano /etc/logrotate.d/apache2 Replace reload with restart

PHP 5.6 (for Communect)


sudo apt-add-repository -y ppa:ondrej/php
sudo apt-get -y update
sudo apt-get -y install php5.6-mysql php5.6-cli php5.6-curl php5.6-json php5.6-sqlite3 php5.6-mcrypt php5.6-curl php5.6-mcrypt php5.6-curl php5.6-gd php5.6-xml php5.6-xmlrpc php5.6-mbstring libapache2-mod-php5.6 php5.6-zip php5.6-dev php5.6-mongo php5.6-mongodb
sudo a2dismod php7.1 ; sudo a2enmod php5.6 ; sudo service apache2 restart ; echo 1 | sudo update-alternatives --config php

Optimize MySQL

systemctl edit mysql
systemctl daemon-reload
service mysql reload

More info

Changing values for Ubuntu 16.04

Report for optimization software


https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-phpmyadmin-on-ubuntu-16-04 : use the same password for phpMyAdmin as for MySQL



sudo nano /etc/mailname

Enter domain name here (ex : domain.ext)

sudo nano /etc/aliases
# See man 5 aliases for format
postmaster:    root
root:          webmaster@mail.ext
monit: root

Access to the server with authentication (SSH and SFTP)

On your local computer, if you don't already have, create a public (~/.ssh/id_rsa.pub) and a private key (~/.ssh/id_rsa) (give a long pass phrase), protect your private key, save the pass phrase to avoid typing it at each connexion and display your public key :

ssh-keygen -t rsa
chmod 400 ~/.ssh/id_rsa
ssh-add ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub

Add the public key on the distant server file ~/.ssh/authorized_keys by pasting it in a new line. Connect by SSH or SFTP : ssh web@ or ssh ubuntu@

If you want to create your keys in specific files :

ssh-keygen -t rsa -f ~/.ssh/id_rsa_name_of_your_choice
nano ~/.ssh/config
User web (or ubuntu)
IdentityFile /Users/username/.ssh/id_rsa_name_of_your_choice

www-data account


sudo su
adduser web
apt-get -y install bindfs
mkdir -p /home/web/www
chown web:web /home/web/www
chmod 755 /home/web/www
nano /etc/fstab


bindfs#/var/www /home/web/www fuse force-user=web,force-group=web,create-for-user=www-data,create-for-group=www-data,create-with-perms=0755,chgrp-ignore,chown-ignore,chmod-ignore 0 0
mount /home/web/www
nano /etc/rc.local

Add this line just before exit 0

    mount /home/web/www &

IMPORTANT : Now, to write in /var/www as www-data user, you must use the web user and access /var/www threw /home/web/www



and then


SSL for HTTPS with Letsencrypt


sudo su
add-apt-repository ppa:certbot/certbot
apt update
apt install python-certbot-apache
ufw allow 443
crontab -e

Add : 15 3 * * * /usr/bin/certbot renew --quiet

To create a certificate to a domain (must be setup on apache2 with a2ensite /etc/apache2/sites-avalaible/domain.ext.conf; service apache2 reload;)

certbot --apache -d domain.ext

If doesn't work :

certbot --authenticator webroot --installer apache -d domain.ext

webroot is the folder where the website is installed

A new file is created : /etc/apache2/sites-available/domain.ext-le-ssl.conf


Each web app needs a specific version of Node.js. So create a new user for each web app and install Node.Js locally.

  1. Install NVM (Node version manager) : https://github.com/creationix/nvm#install-script
  2. edit the package.json file of the web app, look at the node version, and install node : nvm install 6.x.x; nvm use 6.x.x;. If you want the stable version : nvm install stable; nvm use stable;. LTS (recommanded) : nvm install --lts; nvm use --lts;
  3. Node.Js and NPM (Node Package Manager) will be installed

But if Node.js is executed by apache (using the system() or exec() command), Node.Js needs to be installed globally :

sudo apt install nodejs


Not finalized, to resume

Warning before apt-get install phpldapadmin ! Check afterwards weather apache server still works, otherwise you have to do an apt-get remove --purge apache2 then reinstall, add modules that are missing a2enmod and show the list ls /etc/apache2/mods-available/ , add sites-availables, reconfigure HTTPS

Warning : it will appear only at install, it is necessary to choose a subdomain not to interact with another site, but I'm not sure.

First create the subdomain under apache a2ensite ldap.make.social.conf and publish it in HTTPS : certbot --apache -d ldap.make.social


If apache does not work anymore after the installation : https://support.plesk.com/hc/en-us/articles/213946305-Apache-crashes-on-reload-and-websites-show-502-Bad-Gateway-seg-fault-or-similar-nasty-error-detected-in-the-parent-process

local backups


Note the postgress container ID :

sudo docker ps -a

Create a backup script in the file /var/www/backups/scripts/hackmd.sh :

DATE=`date +"%Y-%m-%d_%H-%M-%S"`
docker exec 80c6a4ef581a pg_dump hackmd -U postgres > /var/www/backups/hackmd/$DATE.sql
find /var/www/backups/hackmd/* -mtime +30 -exec rm {} \;

if find /var/www/backups/hackmd/$DATE.sql -type f -size +10c 2>/dev/null | grep -q .; then
    echo "The backup has run successfully"
    echo "The backup has was unsuccessful"
    echo "La sauvegarde de HackMd a echoue. C est probablement l identifiant du conteneur posgress du docker qui a change" | mail -s "Probleme de sauvegarde sur le serveur Infomaniak" contact@marc.fun

Then schedule the daily backups of the database :

sudo crontab -e

and add :

1 3  * *  * /var/www/backups/scripts/hackmd.sh


Create a backup script in the file /var/www/backups/scripts/mongodb.sh :

DATE=`date +"%Y-%m-%d_%H-%M-%S"`
mongodump --out /var/www/backups/mongodb/$DATE  --gzip
find /var/www/backups/mongodb/* -mtime +30 -exec rm -rf {} \;

Then schedule the daily backups of the database :

sudo crontab -e

and add :

3 3  * *  * /var/www/backups/scripts/mongodb.sh

Nextcloud and the other PHP/MySQL applications

su ubuntu
mkdir /home/web/www/backups-full-local
mkdir /home/web/www/backups
cd /home/web/www/backups
mkdir weekly
mkdir weekly/MySql
mkdir weekly/Zip
mkdir daily
mkdir daily/MySql
mkdir daily/Zip
mkdir hourly
mkdir hourly/MySql
mkdir hourly/Zip
cd /home/ubuntu
git clone https://gitlab.com/funkycram/files-and-sql-backup.git
cd files-and-sql-backup/configs
cp example.inc.php weekly-backup.inc.php
cp example.inc.php daily-backup.inc.php
cp example.inc.php hourly-backup.inc.php
chmod 700 *

Edit the file *.inc.php

sudo crontab -e :

5 4  * * 3 zip /var/www/backups-full-local/etc-backup.zip /etc -r
10 4  * * 3 zip /var/www/backups-full-local/home-and-var-www-backup.zip /home -r -x /home/web/www/backups/\*
5 3  * * 7 php /home/ubuntu/files-and-sql-backup/backup.php config=weekly-backup.inc.php
5 3  * * 1-6 php /home/ubuntu/files-and-sql-backup/backup.php config=daily-backup.inc.php
5 0  * * * php /home/ubuntu/files-and-sql-backup/backup.php config=hourly-backup.inc.php

Backups on the Hubic cloud server

  1. Create an account Hubic (we use the account contact@openappecosystem.cc)
  2. Create a folder called "backups"

On the server as root user :

  1. Install rclone
  2. Configure rclone for Hubic (leave blank "Hubic Client Id" and "Hubic Client Secret" and open to the URL asked at the end of the process in a second SSH terminal using elinks)
  3. crontab -e :
    5 5  * *  * rclone --checkers=1 sync /var/www/backups remote:default/backups --dump-bodies

Interesting article if you want to encrypt backups : http://nogues.pro/blog/backup-hubic-duplicity-rsync.html

Copies of system files

su root; crontab -e :

15 3 * * * /usr/bin/certbot renew --quiet
20 3 * * * /usr/bin/certbot renew --quiet --renew-hook /usr/local/bin/renew.sh
1 3  * *  * /var/www/backups/scripts/hackmd.sh
3 3  * *  * /var/www/backups/scripts/mongodb.sh
5 3  * *  * php /var/www/backups/files-and-sql-backup/backup.php config=all.inc.php
5 4  * *  * rclone sync /var/www/backups remote:default/backups

su web; crontab -e :

*/2 * * * * curl https://co2.make.social/co2/test/docron
15 3 * * * curl https://wiki.communecter.org/fr/update-gitbook.php
17 3 * * * curl https://wiki.communecter.org/en/update-gitbook.php
20 3 * * * curl https://doc.cosystem.cc/update-gitbook.php
30 * * * * /home/web/www/ecolesinnovantes.info/public_html/protected/yii cron/hourly >/dev/null 2>&1
00 18 * * * /home/web/www/ecolesinnovantes.info/public_html/protected/yii cron/daily >/dev/null 2>&1

sudo nano /etc/rc.local :

mount /home/web/www &
/var/www/keycloak/keycloak-server/bin/standalone.sh &
docker-compose -f /var/www/docker/docker-hackmd/docker-compose.yml up &
#su ubuntu -c 'cd /var/www/wiki.communecter.org; node wiki start'
su dialoguea -c "/var/www/dialoguea.co.tools/dialoguea/start-server.sh" &
su cryptpad -c "/var/www/cryptpad.co.tools/cryptpad/start-server.sh" &
exit 0

Increase partition size

If disk space has been increased with Infomaniak, the partition must be increased to the new size : xfs_growfs -d /var/www

Configuring tools for internal use

Nextcloud and Collabora online

Nextcloud and Collabora online installation & configuration


Ubuntu 16.04 server + LAMP + sudo apt install smbclient

Installation of NextCloud

  1. Fetch Nextcloud
su web
mkdir ~/www/cloud.communecter.org
cd ~/www/cloud.communecter.org
wget https://download.nextcloud.com/server/releases/nextcloud-xxx.zip
unzip nextcloud-xxx.zip -d .
mv nextcloud/ public_html
mkdir data

Add the icons of external applications in nextcloud/apps/external/img which are in the zip file

  1. Configure apache

  2. Go to https://cloud.communecter.org to configure it

  3. Edit the file config/config.php :

array (
    0 => 'localhost',
    1 => 'cloud.communecter.org',
    2 => 'cloud.co.tools',
    3 => 'nextcloud.co.tools',
    4 => '',

Installation of Collabora

Follow these instructions : https://nextcloud.com/collaboraonline/ Docker alternative : https://hub.docker.com/r/thedarkknight/libreoffice-online-unlimited/

Configure apache in /etc/apache2/site-availables :

    <VirtualHost *:80>
                        ServerName collabora.co.tools

                        SSLHonorCipherOrder     on

                        # Encoded slashes need to be allowed
                        AllowEncodedSlashes NoDecode

                        # Container uses a unique non-signed certificate
                        SSLProxyEngine On
                        SSLProxyVerify None
                        SSLProxyCheckPeerCN Off
                        SSLProxyCheckPeerName Off

                        # keep the host
                        ProxyPreserveHost On

                        # static html, js, images, etc. served from loolwsd
                        # loleaflet is the client part of LibreOffice Online
                        ProxyPass           /loleaflet retry=0
                        ProxyPassReverse    /loleaflet

                        # WOPI discovery URL
                        ProxyPass           /hosting/discovery retry=0
                        ProxyPassReverse    /hosting/discovery

                        # Main websocket
                        ProxyPassMatch "/lool/(.*)/ws$" wss://$1/ws nocanon

                        # Admin Console websocket
                        ProxyPass   /lool/adminws wss://

                        # Download as, Fullscreen presentation and Image upload operations
                        ProxyPass           /lool
                        ProxyPassReverse    /lool

Fetch and launch docker (the option --restart always will cause the container to be added to service docker which is automatically launched at the start of the computer)

sudo su
docker pull collabora/code
ufw allow 9980
docker run -t -d -p -e 'domain=cloud\\.communecter\\.org\|cloud\\.openappecosystem\\.cc\|nextcloud\\.co\\.tools|cloud\\.co\\.tools|cloud\\.cosystem\\.cc' --restart always --cap-add MKNOD collabora/code

Then, in the web interface of NextCloud, add the application Collabora and configure it by giving the server address : https://collabora.co.tools

Configuring tools for internal use


Install and configuration of HackMd

Based on node.js

Installation with docker



sudo apt install docker-compose

Installing docker

sudo su
mkdir /var/www/docker
cd /var/www/docker    
git clone https://github.com/hackmdio/docker-hackmd.git
cd docker-hackmd
docker-compose up

Configuring reverse proxy with apache :

ProxyPass /
ProxyPassReverse /
ProxyRequests Off
ProxyPreserveHost Off

Launch at machine startup

sudo nano /etc/rc.local

Add this line :

docker-compose -f /var/www/docker/docker-hackmd/docker-compose.yml up &

In short, my unsuccessful attempt to install without docker

To complete this notice : https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-16-04 And replace everything that is nvm install 6.0.0 then with 6.11.1 (not the latest version)

su ubuntu cd /var/www/wiki.communecter.org

git clone https://github.com/hackmdio/hackmd.git cd hackmd

sudo npm install -g node-gyp; sudo npm link node-gyp sudo npm install -g webpack; sudo npm link webpack sudo npm install -g common-chunks-webpack-plugin; sudo npm link common-chunks-webpack-plugin sudo npm install -g extract-text-webpack-plugin; sudo npm link extract-text-webpack-plugin sudo npm install -g i18n-webpack-plugin; sudo npm link i18n-webpack-plugin sudo npm install -g compression-webpack-plugin; sudo npm link compression-webpack-plugin sudo npm install -g html-webpack-plugin; sudo npm link html-webpack-plugin sudo npm install -g copy-webpack-plugin; sudo npm link copy-webpack-plugin

sudo ./bin/setup

nano config.json "domain": "test.make.social", "db": { "username": "hackmd", "password": "NSx^1SeT@byuTfYoOXBd", "database": "hackmd", "host": "localhost", "port": "3306", "dialect": "mysql"

NODE_ENV=production HMD_PROTOCOL_USESSL=true DEBUG=false HMD_ALLOW_ORIGIN=localhost,wiki.communecter.org,test.make.social HMD_DB_URL=mysql://localhost:3306/hackmd

sudo npm run build

sudo ufw allow 3000

sudo nodejs app.js


After that add it at server startup :

NODE_ENV=production HMD_PROTOCOL_USESSL=true DEBUG=false HMD_ALLOW_ORIGIN=localhost,wiki.communecter.org,test.make.social HMD_DB_URL=mysql://localhost:3306/hackmd nodejs /var/www/test.make.social/public_html/app.js


This is the Google cache of https://blog.matuni.xyz/archives/2017/05. This is a snapshot of the page as it was posted on May 10, 2017 07:45:36 GMT. The current page may have changed since that date. Learn more Version

Version intégraleVersion in text seulAfficher the sourceAstuce : For finding your search term on this page, press on Ctrl+F or on ⌘+F (Mac), then use the search bar. Archives may 2017 Set up Hackmd on its own server

Written by Mathias B. / 09 may 2017 / no comments
Hello to all,

I wrote this article "Block Notes" because I just finished installing Hackmd for Unixcorn, that by experience I know that it is not a simple software to install and that it will do a little documentation French (the origianl source of the translation is French).

Preparing the server for Hackmd

Here it will be what you want, a VPS (virtual private server), a container on your hypervisor or a similar dedicated server. Please note that once the installation is complete Hackmd does not consume very few resources. Two cores, 2 GB of RAM and a bit of bandwidth will be enough to meet its needs.

Here I created a non-privileged LXC container Debian 8 Jessie, on which I installed NodeJs.

Installation of NodeJs

To do this in the most comfortable way, it is good to go through the official deposits of the project. To do this launch this small script proposes :

curl -sL https://deb.nodesource.com/setup_7.x | bash -

It adds you the deposits, the signature key of the packages and reloads the cache. You just have to launch the installation :

apt install nodejs build-essential

For information the build-essential package is required for installing project dependencies which will be realized a little later.

Preparing the database

I use the PostgreSQL database server here. It runs on another container to which the, created previously, connects via a virtual local network. Let's create the necessary user, his database and assign him a password :

su - postgres psql CREATE USER hackmd; ALTER USER hackmd WITH PASSWORD 'tonsupermotdepasse'; CREATE DATABASE hackmd; \q

To allow access to this database through the network 26/5000 you must adapt the file pb_hba.conf by adding the following line :

host hackmd hackmd adresse.ip.de.hackmd/0 md5

Once done do not forget to relaunch PostgreSQL with a small :

service postgresql restart

Installing Dependencies

Hackmd's developer did it right, the installation itself is very simple. Clone the repository and run the installation script provided, which is summarized in the following steps :

git clone https://github.com/hackmdio/hackmd.git cd hackmd ./bin/setup

Configuring Hackmd

Here comes the time to put the nose in the configuration files. Edit the config.json file and make sure to fill in the following lines correctly :

"production": { "domain": "pad.unixcorn.org", "db": { "username": "hackmd", "password": "votresupermotdepasee", "database": "hackmd", "host": "adresse.ip.de.postgresql", "port": "5432", "dialect": "postgres" },

You should then note the environment variables needed to launch the NodeJs directives, here are the ones I use : NODE_ENV=production HMD_PROTOCOL_USESSL=true

Build and start of the server

We generate the assets with the following command :

NODE_ENV=production HMD_PROTOCOL_USESSL=true npm run build

The operation can take a long time depending on the hardware configuration of your machine, be patient. Once completed you can start the server with the following command :

NODE_ENV=production HMD_PROTOCOL_USESSL=true nodejs app.js

More than configuring your reverse proxy, here I would give the example of configuration of Nginx. Proxy Nginx

The following example takes into account a redirection to HTTPS by default, the integration of Let's Encrypt certificates provided by the acme.sh utility as well as advanced TLS settings (cyphers, HSTS (HTTP Strict Transport Security)...).

server {
  listen 80;
 listen [::]:80;
  server_name votresuper.nomdedomaine.lol;

  # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
  return 301 https://$host$request_uri;

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name votresuper.nomdedomaine.lol;

  # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
  ssl_certificate /root/.acme.sh/pad.unixcorn.org_ecc/fullchain.cer;
  ssl_certificate_key /root/.acme.sh/pad.unixcorn.org_ecc/pad.unixcorn.org.key;
  ssl_session_timeout 1d;
  ssl_session_cache shared:SSL:50m;
 ssl_session_tickets off;

  # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
  ssl_dhparam /etc/ssl/certs/dhparam.pem;

  # modern configuration. tweak to your needs.
  ssl_protocols TLSv1.2;
  ssl_prefer_server_ciphers on;

  # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
  add_header Strict-Transport-Security max-age=15768000;

  # OCSP Stapling ---    # fetch OCSP records from URL in ssl_certificate and cache them
  ssl_stapling on;
  ssl_stapling_verify on;

  ## verify chain of trust of OCSP response using Root CA and Intermediate certs
  ssl_trusted_certificate /root/.acme.sh/pad.unixcorn.org_ecc/ca.cer;

  location / {
  proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header Host $http_host;
   proxy_set_header X-NginX-Proxy true;
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection "upgrade";
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header Host $host;
   proxy_http_version 1.1;
   proxy_pass http://votre.ip.serveur.hackmd:3000;
   proxy_cache_bypass $http_upgrade;
      proxy_redirect off;

Test your configuration, reload it and pop its done!

Configuring tools for internal use


Keycloak IdP for SSO

To explore : http://www.keycloak.org/docs/latest/securing_apps/index.html#_mod_auth_openidc

official website

Server IdP ( identity provider) for the SSO (single sign-on) Application written in Java, runs on a WildFly server.

Installation and configuration

Pre requises (see documentation) :

Fetch the software :

sudo su
add-apt-repository ppa:webupd8team/java
apt update
apt install default-jre oracle-java8-installer

Fetch the software :

cd /var/www
wget https://downloads.jboss.org/keycloak/xxx.Final/keycloak-xxx.Final.zip
unzip keycloak-xxx.Final.zip -d .
cd keycloak-xxx.Final
wget https://downloads.jboss.org/keycloak/xxx.Final/adapters/keycloak-oidc/keycloak-wildfly-adapter-dist-xxx.Final.zip
unzip keycloak-wildfly-adapter-dist-xxx.Final.zip -d .
wget https://downloads.jboss.org/keycloak/xxx.Final/keycloak-proxy-xxx.Final.zip
unzip keycloak-proxy-xxxFinal.zip -d .
rm *.zip

Add the user admin :

./bin/add-user-keycloak.sh -u username

if it returns the message No content to map due to end-of-input, then create a temporary admin user tempuser with the password dkPK62wdofPEK56-_&SO :

nano ./standalone/configuration/keycloak-add-user.json

Put this :

[ {
  "realm" : "master",
  "users" : [{
    "username" : "tempuser",
    "enabled" : true,
    "emailVerified" : true,
    "credentials" : [ {
      "type" : "password",
      "hashedSaltedValue" : "IhS5rpj4PV20PURXYtQktPAYDbI5ATQdafxquCWs1mKwJtuvxhW2DQ0QGNuaQV42MXLSkrLeAyjf4UzlIxm04g==",
      "salt" : "wue854XfHBduqKFcgm9tNQ==",
      "hashIterations" : 100000,
      "algorithm" : "pbkdf2-sha256"
    } ],
    "realmRoles" : [ "admin" ]
  } ]
} ]

Start the server :


When you experience an error at startup, check if it is not a port which is already taken, like port 8080 (we use 8081) or 9990 (we use 9991) In tat case change the config file (at the end) :

nano standalone/configuration/standalone.xml

Access server from outside

Open the ports (adapt the numbers) :

ufw allow 8081
ufw allow 9991

Launch the server on the IP of the network card of the machine :


note the IP of the network card (network adapter)

nano standalone/configuration/standalone.xml

search this phrase : jboss.bind.address.management: and change with the IP address of the network card. Idem for jboss.bind.address

Start the server and go to the address x.x.x.x:8081

Configure SSL to access to the server with HTTPS (apache reverse proxy method)

sudo a2enmod headers
cd /etc/apache2/sites-available

Create the file keycloak.domain.ext.conf

<VirtualHost *:80>
        ServerName keycloak.domain.ext
        ServerAdmin email@domain.ext

        ProxyPass /
        ProxyPassReverse /
        ProxyRequests Off
        ProxyPreserveHost Off

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
a2ensite keycloak.domain.ext.conf 
service apache2 reload
certbot --apache -d keycloak.domain.ext

Edit keycloak.domain.ext.conf and add inside the <VirtualHost *:443> tag :

        ProxyPreserveHost On
        SSLProxyEngine On
        SSLProxyCheckPeerCN on
        SSLProxyCheckPeerExpire on
        RequestHeader set X-Forwarded-Proto "https"
        RequestHeader set X-Forwarded-Port "443"
service apache2 reload

### Configure SSL to access to the server with HTTPS (depreciated method because 8433 port is not reachable by everyone)

1- `nano /usr/local/bin/renew.sh` and put (adjust the 3 variables, YOURPASSWORD musn't contain any special char or space) :


SITE=domain.ext YOURPASSWORD=xxxxxxxxx

for LETSENCRYPTPATH, check the lastest path corresponding to domain.ext. It can be just domain.ext, or domain.ext-0001, or domain.ext-0002, etc.

LETSENCRYPTPATH=domain.ext-0001 KEYCLOAKPATH=/var/www/keycloak

Create the SSL cerficat with Lets'Encrypt

certbot certonly --renew-by-default --standalone -d $SITE --pre-hook "service apache2 stop" --post-hook "service apache2 start"

move to the correct let's encrypt directory

cd /etc/letsencrypt/live/$LETSENCRYPTPATH

copy the files

cp cert.pem /etc/ssl/certs/$SITE.cert.pem cp fullchain.pem /etc/ssl/certs/$SITE.fullchain.pem cp privkey.pem /etc/ssl/private/$SITE.privkey.pem

adjust permissions of the private key

chown :ssl-cert /etc/ssl/private/$SITE.privkey.pem chmod 640 /etc/ssl/private/$SITE.privkey.pem

Add certificate to Wildfly for Keycloak

rm cert_and_key.pkcs12 rm keycloak.jks

Merge the public keys, intermediate and private in a file pkcs12

openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out cert_and_key.pkcs12 -CAfile chain.pem -caname root -name $SITE -password pass:secret

Generate the file jks (for java) from the pkcs12 and assign the passwords

keytool -importkeystore -srckeystore cert_and_key.pkcs12 -srcstoretype PKCS12 -srcstorepass secret -destkeystore keycloak.jks -deststorepass $YOURPASSWORD -destkeypass $YOURPASSWORD

Copy this file into the Keycloak config folder

cp keycloak.jks $KEYCLOAKPATH/standalone/configuration

2- Make the script readable and execute it :

chmod +x /usr/local/bin/renew.sh /usr/local/bin/renew.sh

3- Remember to manually execute it before certificate expiration and reload Keycloak after running `/usr/local/bin/renew.sh`

4- Configure WildFly to accept HTTPS requests
cd /var/www/keycloak/keycloak-xxx.Final
nano standalone/configuration/standalone.xml

For Keycloak 3.2, add the following lines inside `<security-realms> ... </security-realms>` and replace YOURPASSWORD :
<security-realm name="UndertowRealm">
            <keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="YOURPASSWORD" />
For Keycloak 3.3, replace






<http-listener name="default" socket-binding="http" proxy-address-forwarding="true" redirect-socket="proxy-https" />

Add the following line inside `<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}"> ... </socket-binding-group>` :
<socket-binding name="proxy-https" port="443"/>

If needed : http://www.keycloak.org/docs/latest/server_installation/index.html#_network

6- Open port 8443 in the firewall and start the server

ufw allow 8443

Access the server here : https://domain.ext:8443

## Configure the MySQL database
[Official documentation](https://keycloak.gitbooks.io/documentation/content/server_installation/topics/database.html)

sudo su cd /var/www/keycloak mkdir ./modules/system/layers/keycloak/org/mysql mkdir ./modules/system/layers/keycloak/org/mysql/main

Download [the Java module of MySQL](https://dev.mysql.com/downloads/connector/j/)
Unzip and copy the file `mysql-connector-java-x.x.x-bin.jar` to `./modules/system/layers/keycloak/org/mysql/main` then rename it to `mysql-connector-java-bin.jar` and make it executable : `chmod +x modules/system/layers/keycloak/org/mysql/main/mysql-connector-java-bin.jar`

Create the file `/{DOSSIER-KEYCLOAK}/modules/system/layers/keycloak/org/mysql/main/module.xml` and put :

<?xml version="1.0" ?>

    <resource-root path="mysql-connector-java-bin.jar"/>

    <module name="javax.api"/>
    <module name="javax.transaction.api"/>


Create the database `idp_keycloak` (don't use `-` char) with `utf8_general_ci`, create user `idp-keycloak` and give him the rights of this this base.

Caution ! Avoid special characters in the MySQL password like the `&` char.

Edit the file `standalone/configuration/standalone.xml`, replace what is between  `<subsystem xmlns="urn:jboss:domain:datasources:x.x">` and `</subsystem>` with (replace MYSQL-USER-PASSWORD) :
            <datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true">
            <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                <driver name="mysql" module="org.mysql">
                <driver name="h2" module="com.h2database.h2">

Then, before restarting the server, add again a new admin user  (because he was registered in the old database) :
bin/add-user-keycloak.sh -u username

### Launch the Widfly server when the machine starts

sudo nano /etc/rc.local

and add :
`/var/www/keycloak/keycloak-server/bin/standalone.sh &`

## Currently under development 
cd /var/www/keycloak
wget https://downloads.jboss.org/keycloak/3.2.1.Final/adapters/keycloak-oidc/keycloak-wildfly-adapter-dist-3.2.1.Final.zip
unzip keycloak-wildfly-adapter-dist-3.2.1.Final.zip -d .
rm keycloak-wildfly-adapter-dist-3.2.1.Final.zip
cd bin
./jboss-cli.sh --file=adapter-install-offline.cli

## Add an IdP provider

[Example with Facebook](https://symbiotics.co.za/keycloak-social-login-and-sso-solution/)

## Realm configuration

Configure :
- Realm settings :
  - Login : all "on" except "email as username" or "Edit username" ; require SSL -> all requests
  - Email
  - Theme : enable internationalization and select "fr" only
  - Security Defenses (if iframe) : replace Content-Security-Policy by `frame-src 'self' domain.ext sub.domain.ext; frame-ancestors 'self' domain.ext sub.domain.ext; object-src 'self' domain.ext sub.domain.ext;`
  - Tokens : SSO session max : 365 days / Offline Session Idle : 400 days
- Authentification :
  - Passowrd Policy : Digits 1 / Minimum Length : 8 / Not Username / Uppercase Characters : 1

## Mass import users

Create a json file containing, for example (password is `dkPK62wdofPEK56-_&SO`) :

{ "realm": "master", "users" : [ { "username" : "test1", "email" : "test1@mail.ext", "firstName" : "Toto1", "lastName" : "Titi1", "enabled" : true, "emailVerified" : true, "credentials" : [ { "type" : "password", "hashedSaltedValue" : "IhS5rpj4PV20PURXYtQktPAYDbI5ATQdafxquCWs1mKwJtuvxhW2DQ0QGNuaQV42MXLSkrLeAyjf4UzlIxm04g==", "salt" : "wue854XfHBduqKFcgm9tNQ==", "hashIterations" : 100000, "algorithm" : "pbkdf2-sha256" } ], "realmRoles" : [ "offline_access", "uma_authorization" ] }, { "username" : "test2", "email" : "test2@mail.ext", "firstName" : "Toto2", "lastName" : "Titi2", "enabled" : true, "emailVerified" : true, "credentials" : [ { "type" : "password", "hashedSaltedValue" : "IhS5rpj4PV20PURXYtQktPAYDbI5ATQdafxquCWs1mKwJtuvxhW2DQ0QGNuaQV42MXLSkrLeAyjf4UzlIxm04g==", "salt" : "wue854XfHBduqKFcgm9tNQ==", "hashIterations" : 100000, "algorithm" : "pbkdf2-sha256" } ], "realmRoles" : [ "offline_access", "uma_authorization" ] } ] }

And import it in the admin user interface (Manage -> Import)

## Create a new client

Infos : https://domain.ext:8443/auth/realms/master/.well-known/openid-configuration

More info :
- https://www.infoq.com/fr/articles/introduction-openid-connect
- http://www.keycloak.org/docs-api/3.2/rest-api/

The Reaml X.509 Certificate can be found in Realm settings -> Keys -> Certificate

Logout URL : https://domain.ext:8443/auth/realms/master/protocol/openid-connect/logout?redirect_uri=encodedURL

### OpenId Connect

- Client Protocol : openid-connect
- Access Type : confidential
- Standard Flow Enabled : ON
- Implicit Flow Enabled : OFF
- Direct Access Grants Enabled : ON
- Service Accounts Enabled : OFF
- Authorization Enabled : OFF
- Root URL : htts://domain.ext
- Valid Redirect URIs : htts://domain.ext/*
- Fine Grain OpenID Connect Configuration :
    - User Info Signed Response Algorithm : unsigned
    - Request Object Signature Algorithm : any

### Wordpress OpenID Connect Login

1. Create an OpenId Connect client
2. [Install OpenId Connect Generic plugin](https://github.com/daggerhart/openid-connect-generic)
3. Configure :
  - copy/paste the examples (For "OpenID Scope" ([more info here](https://openid.net/specs/openid-connect-basic-1_0.html#Scopes))
  - for the URLs : https://domain.ext:8443/auth/realms/master/.well-known/openid-configuration (Login Endpoint URL = .../auth)
  - check "Identify with User Name, "Link Existing Users", "Redirect Back to Origin Page" and "Alternate Redirect URI"
  - for "Identity Key" : if you connect with a username, use `preferred_username` otherwise use Keyclok id : `sub` for the Identity Key
4. Go to "Settings" -> "Permalinks" and save again the configuration (even if no changes)
5. Add the button : `[openid_connect_generic_login_button]`
6. In `openid-connect-generic-client-wrapper.php` : replace the pattern of `preg_replace` by `'/[^a-zA-Z\-\_0-9]/'`
7. In `openid-connect-generic-login-form.php` : replace `Login with OpenID Connect` by `Login / Sign up`
8. in `openid-connect-generic-client.php` : 
  - remove all the if after `// check the client request state `
  - replace :
    `$id_token_claim = json_decode( base64_decode( $tmp[1] ), TRUE );`
    by :
    $id_token_claim = json_decode(
            str_replace( // because token is encoded in base64 URL (and not just base64)
                array('-', '_'),
                array('+', '/'),
        , TRUE

If doesn't work because of "cURL connection refused" see [this workaround](https://www.digitalocean.com/community/questions/wordpress-wp-cron-curl-connection-refused)

If you want users to connect to Wordpress throw an iframe, add this in the theme `function.php` :

// Allow to connect from an iframe remove_action( 'login_init', 'send_frame_options_header' ); remove_action( 'admin_init', 'send_frame_options_header' );

### Wordpress SAML OneLogin plugin

> Change "master" with your Realm name if different, and 8443 with your custom port if different

In OneLogin settings :

- IdP Identity id : https://URL:8443/auth/realms/master
- Single Sign On Service Url : https://URL:8443/auth/realms/master/protocol/saml
- X.509 Certificate : Keycloak -> Realm settings -> Keys -> Certificate
    - Username : username
    - E-mail : email
    - First Name : first_name
    - Last Name : last_name
    - Role : Role
- ROLE PRECEDENCE : Administrator : 1, Editor : 2, etc.
- Service Provider Entity Id : Keycloak -> Client -> Client ID
- Sign AuthnRequest : Checked
- Sign LogoutRequest : Checked
- Sign LogoutResponse : Checked
- NameIDFormat : ... SAML:2.0  ... persistent
- Service Provider X.509 Certificate & Service Provider Private Key : put a temporary cerficificate
- Signature Algorithm & Digest Algorithm: RSA_SHA256

Click on "Go to the metadata of this SP" (top right) : download in a XML file

In KeyCloak : add a new client

- Select file : the XML file and save

If you need to configure manually :

- Client Id : give any custom name
- Save
- Client protocol : SAML
- Include AuthnStatement : ON
- Sign Documents : ON
- Signature Algorithm : RSA_SHA256
- Canonicalization Method : EXCLUSIVE
- Client Signature Required : ON
- Force POST Binding : ON
- Front Channel Logout : ON
- Name ID Format : persistent
- Valid Redirect URIs : https://wordpress_URL/wp-login.php?saml_acs
- Fine Grain SAML Endpoint Configuration :
    - Assertion Consumer Service POST Binding URL : https://wordpress_URL/wp-login.php?saml_acs
    - Logout Service Redirect Binding URL : https://wordpress_URL/wp-login.php?saml_sls

Tab Mappers

- Roles list -> edit :
    - Role attribute name : Role
    - SAML Attribute NameFormat : unspecified
    - Single Role Attribute : ON
- Create :
    - Name : username
    - Mapper Type : User Property
    - Property : username
    - Friendly Name : username
    - SAML Attribute Name : username
    - SAML Attribute NameFormat : unspecified
- Create again for : email, first_name, last_name

Keycloak -> Client -> Client Id -> SAML Keys -> Generate new keys

Copy values in Onelogin plugin -> Service Provider X.509 Certificate & Service Provider Private Key

### OpenID-Connect-PHP

[OpenID-Connect-PHP GitHub repository](https://github.com/jumbojett/OpenID-Connect-PHP)

It's a simple library that allows an application to authenticate a user through the basic OpenID Connect flow.

Install :

composer require jumbojett/openid-connect-php

Create a test script `test.php`

<?php ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL);

require "./vendor/autoload.php";

$oidc = new OpenIDConnectClient('https://idp.make.social:8443/auth/realms/master', 'OpenID-Connect-PHP', 'b16fbf2b-7aa3-4f02-a488-d3e04f26cb3e');

$oidc->authenticate(); $userInfo = $oidc->requestUserInfo(); $name = $userInfo->preferred_username; // see KeyCloak client Mappers tab (field "Token Claim Name") ?>





    <p>Hello <?php echo $name; ?></p>
    <p>UserInfo array : <?php print_r($userInfo); ?></p>

</body> </html>

### Yii2 OpenIdConnect

#### Install


composer require --prefer-dist yiisoft/yii2-authclient "~2.1.0"

Edit `config/web.php` and add in 'compenents' :
    'authClientCollection' => [
        'class' => 'yii\authclient\Collection',
        'clients' => [
            'YourName' => [
                'class' => 'yii\authclient\clients\Keycloak',
                'issuerUrl' => 'https://domain.ext:8443/auth/realms/master',
                'clientId' => 'KeycloakClientId',
                'clientSecret' => '*************',

#### Start


Open the file `controllers/SiteController.php`, add `use app\components\AuthHandler;` at the beginning of the file, and theses 2 functions inside `class SiteController extends Controller` :
public function actions()
    return [
        'auth' => [
            'class' => 'yii\authclient\AuthAction',
            'successCallback' => [$this, 'onAuthSuccess'],

public function onAuthSuccess($client)
    (new AuthHandler($client))->handle();

The class `class AuthHandler` must be in `components/AuthHandler.php` (create components folder if not exist) and create the file `AuthHandler.php` containing the implementation describe [here](https://github.com/yiisoft/yii2-authclient/blob/master/docs/guide/quick-start.md)

Add the widget in a view file (eg. `views/site/login.php`) :

<?= yii\authclient\widgets\AuthChoice::widget([ 'baseAuthUrl' => ['site/auth'], 'popupMode' => false, ]) ?>

#### Install OpenId Connect


sudo apt update; sudo apt install libgmp-dev php-gmp; sudo service apache2 reload; composer require --prefer-dist "spomky-labs/jose:~5.0.6"

The class OpenIdConnect extends OAuth2
See [OpenId Connect specifications](http://www.yiiframework.com/doc-2.0/yii-authclient-openidconnect.html)

#### Create the Auth.php file if not exist

`nano models/Auth.php` :

<?php namespace app\models; use Yii; class Auth extends \yii\db\ActiveRecord { public static function tableName() { return 'user_auth'; }

public function rules()
    return [
        ['user_id', 'source', 'source_id'], 'required'],

------------.html)'user_id'], 'integer'], ['source', 'source_id'], 'string', 'max' => 255] ]; }

public function attributeLabels()
    return [
        'id' => 'ID',
        'user_id' => 'User ID',
        'source' => 'Source',
        'source_id' => 'Source ID',

public function getUser()
    return $this->hasOne(User::className(), ['id' => 'user_id']);


#### [Create a Keycloak client](https://github.com/yiisoft/yii2-authclient/blob/master/docs/guide/creating-your-own-auth-clients.md)

Create the file `vendor/yiisoft/yii2-authclient/clients/Keycloak.php` containing :


namespace yii\authclient\clients;

use yii\authclient\OpenIdConnect;

class Keycloak extends OpenIdConnect { public function applyAccessTokenToRequest($request, $accessToken) { $data = $request->getData(); $data['Authorization'] = 'Bearer ' . $accessToken->getToken(); $request->setHeaders($data); }

protected function defaultName()
    return 'keycloak';

protected function defaultTitle()
    return 'Centralized authentification';


#### Debug


At the end of `function requestTokens($code)` :

$return = parent::fetchAccessToken($authCode, $params); file_put_contents("/var/www/test.make.social/public_html/test.txt", serialize($return)); return $return;

`cat /var/www/test.make.social/public_html/test.txt`

Copy and paste the token (just after `access_token";s:1746:"`) in https://jwt.io/

### Node.Js with Oauth2


### Symfony OpenIdConnect

1. Install [Symfony 2.8 demo](https://github.com/symfony/demo/releases/tag/v0.8.3)
2. Install [OpenId Connect Relying Party Bundle](https://github.com/waldo2188/OpenIdConnectRelyingPartyBundle/blob/master/Resources/doc/index.md) but replace `"gree/jose": "0.1.7"` with `"gree/jose" : "~2.0"`

Example of config for :
base_url: "https://sso-synfony.marc.fun"
client_id: "sso-symfony-marc-fun"         #OpenID Connect client id given by the OpenId Connect Provider
client_secret: "xxxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxx" #OpenID Connect client secret given by the OpenId Connect Provider
issuer: "https://login.lescommuns.org:8443/auth/realms/master/protocol/openid-connect" #URL of the OpenID Connect Provider
endpoints_url:                  #Part of the URL of the OpenID Connect Provider
    authorization: "/auth"
    token: "/token"
    userinfo: "/userinfo"
    logout: "/logout"
display: "page"                   #How the authentication form will be display to the enduser
scope: "email profile openid offline_access" #List of the scope you need
authentication_ttl: 300         #Maximum age of the authentication
token_ttl: 300                  #Maximum age for tokenID
jwk_url: "https://login.lescommuns.org:8443/auth/realms/master/protocol/openid-connect/certs" #URL to the Json Web Key of OpenID Connect Provider
jwk_cache_ttl: 86400             #Validity periods in second where the JWK store in cache is valid
enabled_state: true             #Enable the use of the state value. This is useful for mitigate replay attack
enabled_nonce: true             #Enable the use of the nonce value. This is useful for mitigate replay attack
enduserinfo_request_method: "POST" #Define the method (POST, GET) used to request the Enduserinfo Endpoint of the OIDC Provider
redirect_after_logout: "https://sso-synfony.marc.fun"           #URI or route name used for redirect user after a logout

Edit `vendor/waldo/openid-connect-relying-party-bundle/Waldo/OpenIdConnect/RelyingPartyBundle/OpenIdConnect/Constraint/IDTokenValidator.php` and comment `$this->errors[] = "Issuer are not the same";` because Keycloak return "https://login.lescommuns.org:8443/auth/realms/master" and the script is comparing to the value of the issuer in `config.yml` wich is "https://login.lescommuns.org:8443/auth/realms/master/protocol/openid-connect"

To show the result of SSO, edit `vendor/waldo/openid-connect-relying-party-bundle/Waldo/OpenIdConnect/RelyingPartyBundle/OpenIdConnect/ResourceOwner/AbstractGenericOICResourceOwner.php` and after `$oicToken->setRawTokenData($content);` add :

echo '

'; print_r($content); echo '
'; exit;


The logout URL is `<a href="{{ path('_oic_rp_logout') }}">Logout</a>`

## Links to explore

- http://blog.keycloak.org/2015/04/running-keycloak-cluster-with-docker.html
- http://rhelblog.redhat.com/2016/03/22/red-hat-federation-story-ipsilon-keycloak-a-clash-of-the-titans/
- http://rhelblog.redhat.com/2016/04/26/why-use-sssd-instead-of-a-direct-ldap-configuration-for-applications/
- https://keycloak.gitbooks.io/server-adminstration-guide/content/topics/user-federation/sssd.html
- https://keycloak.gitbooks.io/securing-client-applications-guide/content/topics/oidc/javascript-adapter.html
- https://github.com/keycloak/keycloak-js-bower
- https://keycloak.gitbooks.io/securing-client-applications-guide/content/topics/oidc/nodejs-adapter.html
- https://github.com/keycloak/keycloak-nodejs-connect
- https://github.com/keycloak/keycloak-nodejs-auth-utils
- http://blog.keycloak.org/2015/08/improved-ldap-integration-with-keycloak.html
- http://keycloak-user.88327.x6.nabble.com/keycloak-user-Create-user-from-keycloak-UI-with-FreeIPA-backend-td1653.html




















1.-install-symfony-2.8-demo 2.-install-openid-connect-relying-party-bundle-but-replace-"gree/jose":-"0.1.7"-with-"gree/jose"-:-"~2.0"







--http://blog.keycloak.org/2015/04/running-keycloak-cluster-with-docker.html --http://rhelblog.redhat.com/2016/03/22/red-hat-federation-story-ipsilon-keycloak-a-clash-of-the-titans/ --http://rhelblog.redhat.com/2016/04/26/why-use-sssd-instead-of-a-direct-ldap-configuration-for-applications/ --https://keycloak.gitbooks.io/server-adminstration-guide/content/topics/user-federation/sssd.html --https://keycloak.gitbooks.io/securing-client-applications-guide/content/topics/oidc/javascript-adapter.html --https://github.com/keycloak/keycloak-js-bower --https://keycloak.gitbooks.io/securing-client-applications-guide/content/topics/oidc/nodejs-adapter.html --https://github.com/keycloak/keycloak-nodejs-connect --https://github.com/keycloak/keycloak-nodejs-auth-utils --http://blog.keycloak.org/2015/08/improved-ldap-integration-with-keycloak.html --http://keycloak-user.88327.x6.nabble.com/keycloak-user-create-user-from-keycloak-ui-with-freeipa-backend-td1653.html .html)

Configuring tools for internal use


With a cron, update the gitbook from the github wiki + a script to make the necessary conversions

Start reading page "Contribute to the documentation"

If necessary : GitBook Toolchain Documentation

Installation and configuration : https://gitlab.com/funkycram/git-wiki-to-gitbook

Configuring tools for internal use


Source : https://github.com/xwiki-labs/cryptpad

CryptPad - Installation & configuration


Source : https://github.com/xwiki-labs/cryptpad/wiki/Installation-guide

Adapt v0.33.6 with the number here

sudo su
mkdir /var/www/cryptpad.co.tools
mkdir /var/www/cryptpad.co.tools/home-user
adduser cryptpad --home /var/www/cryptpad.co.tools/home-user
chown -R cryptpad:cryptpad /var/www/cryptpad.co.tools
ufw allow 2016
su cryptpad
cd /var/www/cryptpad.co.tools
git clone https://github.com/xwiki-labs/cryptpad.git cryptpad
cd cryptpad
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash
nvm install --lts
npm install bower
npm install
bower install
cp config.example.js config.js

Edit config.js :

var domain = ' https://pad.co.tools/';
httpPort: 2016,
httpSafePort: 2017,
myDomain: 'pad.co.tools',
adminEmail: 'contact@communecter.org',

create start-server.sh file and make it executable :

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

cd /var/www/cryptpad.co.tools/cryptpad
node server &

sudo nano /etc/rc.local :

su cryptpad -c "/var/www/cryptpad.co.tools/cryptpad/start-server.sh" &

Install with docker

Source : https://hub.docker.com/r/arno0x0x/docker-cryptpad/

sudo su
ufw allow 2016
docker pull arno0x0x/docker-cryptpad
docker run -d -p 2016:3000 -v /var/www/cryptpad.co.tools/datastore/ arno0x0x/docker-cryptpad


Source : https://github.com/xwiki-labs/cryptpad/wiki/Apache

        ServerName pad.co.tools
        ServerAlias cryptopad.co.tools
        ServerAdmin webmaster@co.tools

        ProxyPass /
        ProxyPassReverse /
        ProxyRequests Off
        ProxyPreserveHost Off

        RewriteEngine on
        RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
        RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
        RewriteRule .* ws://{REQUEST_URI} [P]
Configuring tools for internal use



https://www.bookstackapp.com/docs/admin/installation/ : manual installation



Export pdf


Mise en place

dans le fichier .env, j'ai du paramétrer memcached comme expliqué ici : https://www.bookstackapp.com/docs/admin/cache-session-config/



php artisan config:cache
php artisan config:clear

Bug "page expired"

Toujours un souci de cache ! Du coup j'ai remplacé memcached par database et ça marche !

Configuring tools for internal use


Dialoguea : installation

GitHub repository



sudo su
apt install -y libvips-dev libgsf-1-dev
wget http://dl.google.com/closure-compiler/compiler-latest.tar.gz
tar zxvf compiler-latest.tar.gz
mv closure-compiler-v20170910.jar /usr/share/java/build/compiler.jar
rm compiler-latest.tar.gz

Create a specific user

In order to have a specific version for Dialoguea, we create a specific user for it. Replace DIR by the home directory you want :

sudo adduser dialoguea --home DIR
sudo su dialoguea


nvm install 6.9.4

extra npm packages

npm install -g bower nodemon grunt-cli grunt-closure-compiler
npm install grunt --save-dev
npm install babel fs-extra grunt-contrib-concat


git clone https://github.com/ForumDebats/dialoguea.git
cd dialoguea
npm install
bower install
echo "my53CR3Tkey" > key.pub
cd scripts; ./install-tinyup.sh; cd -;
cd tinymce/plugins/upimage
mv plugin.min.js.off plugin.min.js
cd -


Create the minimified files in public/css (https://www.minifier.org/) :

configure SITE and SMTP in settings.js (for the provider, just add the name : e.g. if your SMTP is smtp.mailgun.com, write mailgun)

Allow 2015 port in firewall, add an admin user and launch the server :

sudo ufw allow 2015
npm run adduser
npm run dev

On the web browser, sign in and create a public group


git pull && grunt

bug or feature requests ?


Make the node.js server start when Ubuntu server starts:

Create the file start-server.sh containing (adapt the cd line) :

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

cd /var/www/dialoguea
npm run dev &

sudo nano /etc/rc.local :

su dialoguea -c "/var/www/dialoguea/start-server.sh" &
Configuring tools for internal use


Wiki.Js install & configuration

official website

based on Node.js

Install as an ubuntu user by following official documentation

Configure the port in config.yml :

title: WikiJS
host: 'https://wikijs.communecter.org'
port: 3003

And the reverse proxy for apache :

        ProxyPass /
        ProxyPassReverse /
        ProxyRequests Off
        ProxyPreserveHost Off

If there is a bug, the command to restart the server is node wiki reload

Replace files in assets with those in this zip file

Edit the file app.js and add the following CSS code just before the 1st character \ de \n\n/*# sourceMappingURL=app.scss.map :

    .nav-left{overflow-x: hidden} .nc-icon-outline.ui-2_layers::before {content: ""; width: 36px; display: block;} a.nav-item {background-image: url("/images/logo-30-36.png");background-repeat: no-repeat;background-position: 10px center;}  .nav-item h1 {font-size: 24px; margin-top: 8px;} .nav.is-indigo .control input[type="text"]:placeholder-shown {color: #e8eaf6}#search-input::-webkit-input-placeholder { color: #e8eaf6 !important; } #search-input:-moz-placeholder { color: #e8eaf6 !important; opacity:  1;}#search-input::-moz-placeholder {color: #e8eaf6 !important;opacity: 1;}#search-input:-ms-input-placeholder {color: #e8eaf6 !important;}#search-input::-ms-input-placeholder {color: #e8eaf6 !important;}#search-input::placeholder {color: #e8eaf6 !important;} .mkcontent a {color: #1976d2; text-decoration: none;} .mkcontent a:hover {text-decoration: underline;} .mkcontent h3 {color: #004d40}

And replace all :