4 - Technical documentation
Configuring tools for internal use
Installed services on the Commons server
| URL | localisation | langage | BDD |
|---|---|---|---|
| cloud.co.tools (nextcloud) | /var/www/cloud.co.tools | php | mysql |
| onlyoffice.co.tools | docker | ||
| login.lescommuns.org (Keycloak) | /var/www/login.lescommuns.org | java | mysql |
| codimd.co.tools | docker | node.js | mysql |
| weblate.co.tools | docker | python | postgres |
| cryptpad.co.tools | /var/www/cryptpad.co.tools | node.js | |
| doc.co.tools (bookstack) | /var/www/doc.co.tools | php | mysql |
Ubuntu server
Installing and configuring the Ubuntu server 16.04
Return to the list of tool configurations
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";
exit
And restart the system or just MySQL : service mysql reload
Set Locale
Schedule server restart every month automaticaly
crontab -e
Add :
#Restart server every first Monday of every month
45 2 1-7 * * [ "$(date '+\%u')" = "1" ] && /sbin/shutdown -r +5
Security
Firewall
sudo ufw allow OpenSSH
sudo ufw deny 21
sudo ufw enable
sudo ufw status
OSSEC
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
./install.sh
choose local (not server) enter email choose default for all others options
nano /var/ossec/etc/ossec.conf add :
<white_list>IPOfTheSever</white_list>
<white_list>MyIP</white_list>
And check email_to and email_from
nano /var/ossec/rules/local_rules.xml add :
<rule id="100013" level="0">
<if_sid>31103</if_sid>
<url>^/phpmyadmin/</url>
<description>Ignoring phpMyAdmin events.</description>
</rule>
<rule id="100014" level="0">
<if_sid>31533</if_sid>
<url>^/s/|^/phpmyadmin/|^/mail/mail/|^/live/poll|^/socket.io|^/index.php?date=|^/xhr_send?t=</url>
<description>Ignoring Humhub Polls module activation events, phpMyAdmin, HackMd (socket.io), Piwik and OnlyOffice.</description>
</rule>
<rule id="100015" level="0">
<if_sid>31151</if_sid>
<url>^/mail/mail/|^/socket.io</url>
<description>Ignoring Humhub Ajax when disconnected, CodiMd (socket.io)</description>
</rule>
Automaticaly add IP in white list
- 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
- edit
nano /var/ossec/etc/ossec.confand in<rules></rules>add:
<list>lists/approved_humhub_list</list>
service ossec restart- 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>
</rule>
id="100016" must be unique, change it if necessary ! 6. 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));
}
GUI
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
./setup.sh
choose www-data
/etc/init.d/apache2 restart
/etc/init.d/ossec start
http://serverIp/ossec
Fail2ban
sudo su
apt install fail2ban
nano /etc/fail2ban/jail.conf
ignoreip = 127.0.0.1/8 cramf.mooo.com
bantime = 900
maxretry = 3
[ssh]
enabled = true
port = ssh,sftp
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
[apache-w00tw00t]
enabled = true
filter = apache-w00tw00t
action = iptables[name=Apache-w00tw00t,port=80,protocol=tcp]
logpath = /var/log/apache2/access*.log
maxretry = 1
[apache-noscript]
enabled = true
[apache-overflows]
enabled = true
[apache-badbots]
enabled = true
nano /etc/fail2ban/filter.d/apache-w00tw00t.conf
[Definition]
failregex = ^<HOST> -.*"GET \/w00tw00t\.at\.ISC\.SANS\.DFind\:\).*".*
ignoreregex =
fail2ban-client reload
fail2ban-client status
Monitoring
apt install apache2 libcgi-fast-perl libapache2-mod-fcgid
a2enmod fcgid
Munin
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 127.0.0.0/8 ::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 127.0.0.0/8 ::1
# AuthUserFile /etc/munin/munin-htpasswd
# AuthName "Munin"
# AuthType Basic
# require valid-user
#</Location>
<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
</IfModule>
</Directory>
# Enables fastcgi for munin-cgi-html if present
#<Location /munin-cgi>
# <IfModule mod_fastcgi.c>
# SetHandler fastcgi-script
# </IfModule>
#</Location>
#<Location /munin-cgi/static>
# SetHandler None
#</Location>
# 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>
<IfModule !mod_fcgid.c>
SetHandler cgi-script
</IfModule>
</Location>
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>
<IfModule !mod_fcgid.c>
SetHandler cgi-script
</IfModule>
</Location>
</VirtualHost>
Monit
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'
LAMP
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 (pour Ubuntu 16.04)
apt install software-properties-common (pour Ubuntu 18.04)
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 php7.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
session.gc_maxlifetime = 2592000
session.gc_maxlifetime enables to stay connected 1 month
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)
https://phpraxis.wordpress.com/2016/05/16/install-php-5-6-or-5-5-in-ubuntu-16-04-lts-xenial-xerus/
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
[Service]
LimitNOFILE=infinity
LimitMEMLOCK=infinity
systemctl daemon-reload
service mysql reload
Changing values for Ubuntu 16.04
Report for optimization software
phpMyAdmin
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@83.166.144.90 or ssh ubuntu@83.166.144.90
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
Host 83.166.144.90
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
add
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
DNS
https://wiki.gandi.net/fr/dns/zone/a-record
and then
https://www.digitalocean.com/community/tutorials/how-to-set-up-apache-virtual-hosts-on-ubuntu-16-04
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
Node.Js
Each web app needs a specific version of Node.js. So create a new user for each web app and install Node.Js locally.
- Install NVM (Node version manager) : https://github.com/creationix/nvm#install-script
- 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; - 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
LDAP
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
HackMd
Note the postgress container ID :
sudo docker ps -a
Create a backup script in the file /var/www/backups/scripts/hackmd.sh :
#!/bin/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"
else
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
fi
Then schedule the daily backups of the database :
sudo crontab -e
and add :
1 3 * * * /var/www/backups/scripts/hackmd.sh
MongoDb
Create a backup script in the file /var/www/backups/scripts/mongodb.sh :
#!/bin/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
- Create an account Hubic (we use the account contact@openappecosystem.cc)
- Create a folder called "backups"
On the server as root user :
- Install rclone
- 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)
-
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 (check if partition system is XFS) :
xfs_growfs -d /var/www
Remove old kernels
uname -r
dpkg --list | grep linux-image
apt --purge remove linux-image-XXX* (XXX is old kernel number)
dpkg --list | grep linux-headers
apt --purge remove linux-headers-XXX*
dpkg --list | grep linux-modules
apt --purge remove linux-modules-XXX*
update-grub2
List largest installed packages
dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n••
Keycloak
-
Keycloak IdP for SSO
To explore : http://www.keycloak.org/docs/latest/securing_apps/index.html#_mod_auth_openidc
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-installerFetch 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 . rm *.zipAdd the user admin :
./bin/add-user-keycloak.sh -u usernameif it returns the message
No content to map due to end-of-input, then create a temporary admin usertempuserwith the passworddkPK62wdofPEK56-_&SO:nano ./standalone/configuration/keycloak-add-user.jsonPut 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 :
./bin/standalone.shWhen 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.xmlAccess server from outside
Open the ports (adapt the numbers) :
ufw allow 8081 ufw allow 9991Launch the server on the IP of the network card of the machine :
ifconfignote the IP of the network card (network adapter)
nano standalone/configuration/standalone.xmlsearch this phrase : jboss.bind.address.management: and change 127.0.0.1 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
With Apache reverse proxy.
nano standalone/configuration/standalone.xmlIn
<http-listener, addproxy-address-forwarding="true"to have :<http-listener name="default" socket-binding="http" redirect-socket="proxy-https" proxy-address-forwarding="true" enable-http2="true"/>sudo a2enmod headers cd /etc/apache2/sites-availableCreate the file
keycloak.domain.ext.conf<VirtualHost *:80> ServerName keycloak.domain.ext ServerAdmin email@domain.ext ProxyPass / http://000.000.000.000:8081/ ProxyPassReverse / http://000.000.000.000:8081/ ProxyRequests Off ProxyPreserveHost Off ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>a2ensite keycloak.domain.ext.conf service apache2 reload certbot --apache -d keycloak.domain.extEdit
keycloak.domain.ext-le-ssland 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 reloadConfigure the MySQL database
sudo su cd /var/www/keycloak mkdir ./modules/system/layers/keycloak/com/mysql mkdir ./modules/system/layers/keycloak/com/mysql/mainDownload the Java module of MySQL (select "Platform independant"). Latest working version is : 5.1.45. So you can directely download with
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.45.zip.Unzip and copy the file
mysql-connector-java-x.x.x-bin.jarto./modules/system/layers/keycloak/com/mysql/main, rename it tomysql-connector-java-bin.jarand make it executable :chmod +x modules/system/layers/keycloak/com/mysql/main/mysql-connector-java-bin.jarnano ./modules/system/layers/keycloak/com/mysql/main/module.xmland put :<?xml version="1.0" ?> <module xmlns="urn:jboss:module:1.3" name="com.mysql"> <resources> <resource-root path="mysql-connector-java-bin.jar"/> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> </dependencies> </module>Create the database
idp_keycloak(don't use-char) withutf8mb4_general_ci, create useridp_keycloakand 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) :<datasources> <datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true" statistics-enabled="${wildfly.datasources.statistics-enabled:${wildfly.statistics-enabled:false}}"> <connection-url>jdbc:mysql://localhost/idp_keycloak?useSSL=false&characterEncoding=UTF-8</connection-url> <driver>mysql</driver> <pool> <max-pool-size>20</max-pool-size> </pool> <security> <user-name>idp_keycloak</user-name> <password>MYSQL-USER-PASSWORD</password> </security> </datasource> <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true"> <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url> <driver>h2</driver> <security> <user-name>sa</user-name> <password>sa</password> </security> </datasource> <drivers> <driver name="mysql" module="com.mysql"> <driver-class>com.mysql.jdbc.Driver</driver-class> </driver> <driver name="h2" module="com.h2database.h2"> <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class> </driver> </drivers> </datasources>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 usernameLaunch the Widfly server when the machine starts
sudo nano /etc/rc.localand 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.cliAdd an IdP provider
Realm configuration
Configure :
- Realm settings :
- Login : all "on" except "email as username" or "Edit username" ; require SSL -> all requests
- 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
Create a custom theme
Official documentation Tutorial
To create theme, remove caching
nano standalone/configuration/standalone.xml:<theme> <staticMaxAge>-1</staticMaxAge> <cacheThemes>false</cacheThemes> <cacheTemplates>false</cacheTemplates>select the custom theme
For the welcome page :
nano standalone/configuration/standalone.xml:<theme> <welcomeTheme>custom-theme</welcomeTheme>For the other pages : go in the administration -> Domain configuration -> theme
When your theme is ready, put back caching
nano standalone/configuration/standalone.xml:<theme> <staticMaxAge>2592000</staticMaxAge> <cacheThemes>true</cacheThemes> <cacheTemplates>true</cacheTemplates>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
- Create an OpenId Connect client
- Install OpenId Connect Generic plugin
- Configure :
- copy/paste the examples (For "OpenID Scope" (more info here)
- 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_usernameotherwise use Keyclok id :subfor the Identity Key
- Go to "Settings" -> "Permalinks" and save again the configuration (even if no changes)
- Add the button :
[openid_connect_generic_login_button] - In
openid-connect-generic-client-wrapper.php: replace the pattern ofpreg_replaceby'/[^a-zA-Z\-\_0-9]/' - In
openid-connect-generic-login-form.php: replaceLogin with OpenID ConnectbyLogin / Sign up - 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( base64_decode( str_replace( // because token is encoded in base64 URL (and not just base64) array('-', '_'), array('+', '/'), $tmp[1] ) ) , TRUE );If doesn't work because of "cURL connection refused" see this workaround
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
- ATTRIBUTE MAPPING :
- 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
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-phpCreate 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") ?> <html> <head> <title>Example OpenID Connect Client Use</title> <style> body { font-family: 'Lucida Grande', Verdana, Arial, sans-serif; } </style> </head> <body> <div> <p>Hello <?php echo $name; ?></p> <p>UserInfo array : <?php print_r($userInfo); ?></p> </div> </body> </html>Yii2 OpenIdConnect
Install
composer require --prefer-dist yiisoft/yii2-authclient "~2.1.0"Edit
config/web.phpand 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, adduse app\components\AuthHandler;at the beginning of the file, and theses 2 functions insideclass 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 AuthHandlermust be incomponents/AuthHandler.php(create components folder if not exist) and create the fileAuthHandler.phpcontaining the implementation describe hereAdd 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
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'], [['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
Create the file
vendor/yiisoft/yii2-authclient/clients/Keycloak.phpcontaining :<?php namespace yii\authclient\clients; use yii\authclient\OpenIdConnect; class Keycloak extends OpenIdConnect { public function applyAccessTokenToRequest($request, $accessToken) { $data = $request->getData(); $request->setHeaders($data); } protected function defaultName() { return 'keycloak'; } protected function defaultTitle() { return 'Centralized authentification'; } }Debug
vendor/yiisoft/yii2-authclient/OpenIdConnect.php
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.txtCopy and paste the token (just after
access_token";s:1746:") in https://jwt.io/Node.Js with Oauth2
Symfony OpenIdConnect
- Install Symfony 2.8 demo
- Install OpenId Connect Relying Party Bundle 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 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 logoutEdit
vendor/waldo/openid-connect-relying-party-bundle/Waldo/OpenIdConnect/RelyingPartyBundle/OpenIdConnect/Constraint/IDTokenValidator.phpand 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 inconfig.ymlwich 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.phpand after$oicToken->setRawTokenData($content);add :echo '<pre>'; print_r($content); echo '</pre>'; exit;The logout URL is
<a href="{{ path('_oic_rp_logout') }}">Logout</a>Upgrading
https://www.keycloak.org/docs/latest/release_notes/ https://www.keycloak.org/docs/latest/upgrading
- Prepare an other instance of Keycloak (see above), including Widfly and MySQL adaptors. Do not add users.
- Copy database (to a new one),
standalonedirectory (updatestandalone.xmlwith new database name) and custom theme from the old Keycloak. - Stop the old server to avoid ports conflicts.
- When the new server is lunched, standalone.xml file and database are - automatically updated for the new version.
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
- Realm settings :
CodiMD
Install and configuration of HackMd
Based on node.js
Installation with docker
Pre-requisites
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04
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 / http://83.166.144.90:3000/
ProxyPassReverse / http://83.166.144.90:3000/
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
https://github.com/hackmdio/hackmd/issues/86
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_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
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!
CryptPad
Source : https://github.com/xwiki-labs/cryptpad
CryptPad - Installation & configuration
Install
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 :
#!/bin/bash
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
Apache
Source : https://github.com/xwiki-labs/cryptpad/wiki/Apache
ServerName pad.co.tools
ServerAlias cryptopad.co.tools
ServerAdmin webmaster@co.tools
ProxyPass / http://83.166.144.90:2016/
ProxyPassReverse / http://83.166.144.90:2016/
ProxyRequests Off
ProxyPreserveHost Off
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule .* ws://83.166.144.90:2016%{REQUEST_URI} [P]
Weblate
Install and configuration of Weblate
Docker install
Following steps in:
https://docs.weblate.org/en/latest/admin/deployments.html#docker
Steps done:
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_EMAIL_HOST_USER=wave
- WEBLATE_EMAIL_HOST_PASSWORD=pass
- 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_PASSWORD=pass
- WEBLATE_ADMIN_EMAIL=wave@communecter.org
- WEBLATE_ADMIN_NAME="Administrateur"
- WEBLATE_IP_PROXY_HEADER=HTTP_X_FORWARDED_FOR
- WEBLATE_REGISTRATION_OPEN=1
- WEBLATE_ENABLE_HTTPS=1
- WEBLATE_SOCIAL_AUTH_GITLAB_KEY=application id
- WEBLATE_SOCIAL_AUTH_GITLAB_SECRET=secret
- 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
</VirtualHost>
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
</VirtualHost>
</IfModule>
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/
</VirtualHost>
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 :
- Add a first component to your project. This component should translate a file that will not move in the future (for example, I chose the common.php file for pixel-humain project).
- Then, enable the component discovery addon to automatically generate components. The translations of these components will be committed in the repo of the first component you created (common.php in my example). To push to Weblate repository, use the Repository management menu of the main component.
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 :
- 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.
- set a webhook in the main repository to the weblate URL :
https://weblate.co.tools/hooks/gitlab/
The workflow should be like below :
- 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.
- As Translators, you work on the translations. When you are ready, you can push to the push repository using Weblate interface.
- 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.
Nextcloud and Collabora online
Nextcloud and Collabora online installation & configuration
Prerequisite
Ubuntu 16.04 server + LAMP + sudo apt install smbclient
Installation of NextCloud
- 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
-
Configure apache
-
Go to https://cloud.communecter.org to configure it
-
Edit the file config/config.php :
array (
0 => 'localhost',
1 => 'cloud.communecter.org',
2 => 'cloud.co.tools',
3 => 'nextcloud.co.tools',
4 => '83.166.144.90',
),
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 https://127.0.0.1:9980/loleaflet retry=0
ProxyPassReverse /loleaflet https://127.0.0.1:9980/loleaflet
# WOPI discovery URL
ProxyPass /hosting/discovery https://127.0.0.1:9980/hosting/discovery retry=0
ProxyPassReverse /hosting/discovery https://127.0.0.1:9980/hosting/discovery
# Main websocket
ProxyPassMatch "/lool/(.*)/ws$" wss://127.0.0.1:9980/lool/$1/ws nocanon
# Admin Console websocket
ProxyPass /lool/adminws wss://127.0.0.1:9980/lool/adminws
# Download as, Fullscreen presentation and Image upload operations
ProxyPass /lool https://127.0.0.1:9980/lool
ProxyPassReverse /lool https://127.0.0.1:9980/lool
</VirtualHost>
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 127.0.0.1:9980:9980 -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
GitBook
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
BookStack
Installation
https://www.bookstackapp.com/docs/admin/installation/ : manual installation
Update
https://www.bookstackapp.com/docs/admin/updates
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/
CACHE_DRIVER=memcached
SESSION_DRIVER=memcached
and
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 !
Dialoguea (Obsolete)
Dialoguea : installation
requirements
system
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
node.js
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
Install
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 -
grunt
Create the minimified files in public/css (https://www.minifier.org/) :
- content.min.css
- dialoguea.min.css
- skin.min.css
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
Update
git pull && grunt
bug or feature requests ?
https://github.com/ForumDebats/dialoguea/issues
Make the node.js server start when Ubuntu server starts:
Create the file start-server.sh containing (adapt the cd line) :
#!/bin/bash
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" &
Wiki.JS (Obsolete)
Wiki.Js install & configuration
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 / http://83.166.144.90:3003/
ProxyPassReverse / http://83.166.144.90:3003/
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 :
-
#3f51b5with#E33551 -
#283593with#c5203b -
#3949ABwith#de314d -
#5c6bc0with#4a4a4a