Je suis en train de fabriquer des placards. Alors j’ai cherché comment aménager ces derniers. Voici quelques idées.
Cette première version plus adapté pour une personne seule :
Après avoir joué un peu avec le Mastodon et docker, j’ai eu envie de le déployer correctement. Je reprends l’article d’Agristan : https://angristan.fr/installer-instance-mastodon-debian-8/
J’ai déjà ma propre installation, j’installe Yarn.
npm install -g yarn
apt install redis-server redis-tools
apt-get install postgresql postgresql-contrib
On crée un utilisateur et une base de données :
su - postgres psql CREATE USER mastodon CREATEDB; \q exit
On va mettre en place l’environnement de Mastodon avec cet utilisateur.
adduser --disabled-password --disabled-login mastodon
Pour se loger :
su - mastodon
apt install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
On se connecte avec l’utilisateur mastodon
su - mastodon git clone https://github.com/rbenv/rbenv.git ~/.rbenv cd ~/.rbenv && src/configure && make -C src echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
On se reconnecte pour prendre en compte le nouvel environnement
exit su - mastodon
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 2.4.1
Cela peut prendre quelques minutes ou quelques dizaines de minutes suivant la puissance de votre serveur.
cd ~ git clone https://github.com/tootsuite/mastodon.git live cd live
Ensuite, on va utiliser la dernière version stable plutôt que le dépôt de développement continuellement mis à jour.
Note : $(git tag | tail -n 1)
est une commande qui récupère automatiquement le dernier tag, c’est à dire le numéro de la dernière version.
git checkout $(git tag | tail -n 1)
Ensuite on installe le reste :
gem install bundler
bundle install --deployment --without development test
bundle install --with development
yarn install
Pour la configuration voir plus bas.
RAILS_ENV=production bundle exec rails db:setup
RAILS_ENV=production bundle exec rails assets:precompile
Pour fonctionner, Mastodon a besoin de 3 services. Pour pouvoir les gérer facilement, on va utiliser des scripts systemd.
À faire en root.
vi /etc/systemd/system/mastodon-web.service
Collez :
[Unit] Description=mastodon-web After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/home/mastodon/live Environment="RAILS_ENV=production" Environment="PORT=3000" ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb TimeoutSec=15 Restart=always [Install] WantedBy=multi-user.target
vi /etc/systemd/system/mastodon-sidekiq.service
Collez :
[Unit] Description=mastodon-sidekiq After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/home/mastodon/live Environment="RAILS_ENV=production" Environment="DB_POOL=20" ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 20 -q default -q mailers -q pull -q push TimeoutSec=15 Restart=always [Install] WantedBy=multi-user.target
vi /etc/systemd/system/mastodon-streaming.service
Collez :
[Unit] Description=mastodon-streaming After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/home/mastodon/live Environment="NODE_ENV=production" Environment="PORT=4000" ExecStart=/usr/bin/npm run start TimeoutSec=15 Restart=always [Install] WantedBy=multi-user.target
On active les services :
systemctl enable /etc/systemd/system/mastodon-*.service
Et on démarre le bazar :
systemctl start mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
Si vous modifiez la configuration :
systemctl restart mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
Pour vérifier que tout est en route :
systemctl status mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
Il y a souvent des mises à jour de Mastodon, surtout en ce moment. Pour mettre à jour votre instance, c’est très simple.
Sauvegarder les fichiers et la base de données avant de mettre à jour.
Déjà, une petite mise à jour des paquets ne fait pas de mal :
apt update && apt full-upgrade
On arrête tout :
systemctl stop mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
On récupère les sources, et on met à jour Mastodon, les dépendances Ruby et npm, on régénère les assets et on met à jour la BDD.
Note : $(git tag | tail -n 1)
est une commande qui récupère automatiquement le dernier tag, c’est à dire le numéro de la dernière version.
Aussi, toutes ces commandes ne sont pas forcément nécessaires à chaque fois, mais les exécuter ne vous fera pas de mal 😉 . Je vous recommande de lire les notes de versions avant de mettre à jour.
su - mastodon cd live git fetch git checkout $(git tag | tail -n 1) bundle install npm upgrade yarn yarn install RAILS_ENV=production bundle exec rails assets:clean RAILS_ENV=production bundle exec rails assets:precompile RAILS_ENV=production bundle exec rails db:migrate exit
Et on redémarre tout :
systemctl start mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
On édite le crontab :
crontab -e -u mastodon
Et on y ajoute :
@daily cd /home/mastodon/live && RAILS_ENV=production /home/mastodon/.rbenv/shims/bundle exec rake mastodon:daily
On installe Nginx stable depuis les dépôts officiels :
wget -O - https://nginx.org/keys/nginx_signing.key | apt-key add - echo "deb http://nginx.org/packages/debian/ $(lsb_release -sc) nginx" > /etc/apt/sources.list.d/nginx.list apt update apt install nginx
On ajoute la configuration :
nano /etc/nginx/conf.d/mastodon.conf
Et on y met (à adapter, ici c’est pour mstdn.io) :
map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; listen [::]:80; server_name www.mstdn.io mstdn.io; # On redirige tout en HTTPS return 301 https://mstdn.io$request_uri; access_log /dev/null; error_log /dev/null; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name www.mstdn.io mstdn.io; # Ne s'applique pas si vous utilisez un sous-domaine if ($host = www.mstdn.io) { return 301 https://mstdn.io$request_uri; } access_log /var/log/nginx/mstdn-access.log; error_log /var/log/nginx/mstdn-error.log; # HTTPS ssl_certificate /etc/letsencrypt/live/www.mstdn.io/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.mstdn.io/privkey.pem; ssl_protocols TLSv1.2; ssl_ecdh_curve prime256v1; ssl_ciphers EECDH+AESGCM:EECDH+AES; ssl_prefer_server_ciphers on; resolver 80.67.169.12 80.67.169.40 valid=300s; resolver_timeout 5s; ssl_session_cache shared:SSL:10m; add_header Strict-Transport-Security "max-age=15768000"; add_header Referrer-Policy "strict-origin-when-cross-origin"; #Domaine à apdater à la fin add_header Content-Security-Policy "default-src 'none'; font-src 'self'; media-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self'; img-src 'self' data:; connect-src 'self' wss://mstdn.io; frame-ancestors 'none';"; root /home/mastodon/live/public; location / { try_files $uri @proxy; } location @proxy { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_pass_header Server; proxy_pass http://127.0.0.1:3000; proxy_buffering off; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } location /api/v1/streaming { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_pass http://127.0.0.1:4000; proxy_buffering off; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } error_page 500 501 502 503 504 /500.html; }
Avec une belle configuration HTTPS inclue. 🙂
Pour que tout ça soit fonctionnel on va générer les certificats correspondants au domaine.
Mastodon est un réseau social de micro-blogging libre et décentralisé. Il est une bonne alternative à Twitter. Voici comment tester un peu ses possibilités.
Avoir installé Docker.
Pour faire simple (bien que brutal) cloner le dépôt Github du projet.
$ git clone https://github.com/tootsuite/mastodon.git
Ensuite copier et éditer le fichier de configuration.
$ cp .env.production.sample .env.production
L’éditer et remplir les champs suivants :
LOCAL_DOMAIN=
# d'abord remplis avec localhost j'ai ensuite laissé vide parce que mon instance est locale (pour mes tests)LOCAL_HTTPS=false # true si certificat
Pour la configuration SMTP utiliser Mailgun ou tout autre serveur SMTP.
SMTP_SERVER=smtp.mailgun.org SMTP_PORT=587 SMTP_LOGIN=toto SMTP_PASSWORD=1234 SMTP_FROM_ADDRESS=notifications@example.com SMTP_DOMAIN=example.com
Ajouter l’option SMTP_DOMAIN ce qui vous évitera des heures de recherches.
Lancer ensuite un build
docker-compose build
Puis générer la clé secrète
docker-compose run --rm web rake secret
Si tout ce passe bien recopier la clé dans le fichier .env.production
Créer la base de données
docker-compose run --rm web rails db:migrate
Et compiler les assets
docker-compose run --rm web rails assets:precompile
Vous pouver lancer le monstre :
docker-compose up
Ou en mode démon :
docker-compose up -d
Connectez vous sur le port 3000 : http://localhost:3000
# Service dependencies REDIS_HOST=redis REDIS_PORT=6379 DB_HOST=db DB_USER=postgres DB_NAME=postgres DB_PASS= DB_PORT=5432 # Federation LOCAL_DOMAIN= LOCAL_HTTPS=false # Application secrets # Generate each with the `rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose) PAPERCLIP_SECRET= SECRET_KEY_BASE=<secret> OTP_SECRET= # Registrations # Single user mode will disable registrations and redirect frontpage to the first profile # SINGLE_USER_MODE=true # Prevent registrations with following e-mail domains # EMAIL_DOMAIN_BLACKLIST=example1.com|example2.de|etc # Only allow registrations with the following e-mail domains # EMAIL_DOMAIN_WHITELIST=example1.com|example2.de|etc # Optionally change default language DEFAULT_LOCALE=fr # E-mail configuration # Note: Mailgun and SparkPost (https://sparkpo.st/smtp) each have good free tiers SMTP_SERVER=smtp.mailgun.org SMTP_PORT=587 SMTP_LOGIN= SMTP_PASSWORD= SMTP_FROM_ADDRESS=notifications@example.com #SMTP_DELIVERY_METHOD=smtp # delivery method can also be sendmail #SMTP_AUTH_METHOD=plain #SMTP_OPENSSL_VERIFY_MODE=peer #SMTP_ENABLE_STARTTLS_AUTO=true # Optional asset host for multi-server setups # CDN_HOST=assets.example.com # S3 (optional) # S3_ENABLED=true # S3_BUCKET= # AWS_ACCESS_KEY_ID= # AWS_SECRET_ACCESS_KEY= # S3_REGION= # S3_PROTOCOL=http # S3_HOSTNAME=192.168.1.123:9000 # S3 (Minio Config (optional) Please check Minio instance for details) # S3_ENABLED=true # S3_BUCKET= # AWS_ACCESS_KEY_ID= # AWS_SECRET_ACCESS_KEY= # S3_REGION= # S3_PROTOCOL=https # S3_HOSTNAME= # S3_ENDPOINT= # Optional alias for S3 if you want to use Cloudfront or Cloudflare in front # S3_CLOUDFRONT_HOST= # Streaming API integration # STREAMING_API_BASE_URL= # Advanced settings # If you need to use pgBouncer, you need to disable prepared statements: # PREPARED_STATEMENTS=false
Créer un utilisateur avec l’interface de création de compte et le définir comme administrateur.
docker-compose run --rm web rails mastodon:make_admin USERNAME=<user>
https://angristan.fr/installer-instance-mastodon-debian-8/
https://blog.lertsenem.com/creer-son-instance-mastodon-perso-vite-fait-mal-fait-fr.html
Docker est un logiciel libre qui automatise le déploiement d’applications dans des conteneurs logiciels. Selon la firme de recherche sur l’industrie 451 Research, « Docker est un outil qui peut empaqueter une application et ses dépendances dans un conteneur isolé, qui pourra être exécuté sur n’importe quel serveur Linux ». Ceci permet d’étendre la flexibilité et la portabilité d’exécution d’une application, que ce soit sur la machine locale, un cloud privé ou public, une machine nue, etc.
Se Connecter avec l’utilisateur root ou préfixer les commandes par sudo.
apt remove docker docker-engine
Installation des outils
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
Ajouter la ligne suivante au fichier /etc/apt/sources.list
deb [arch=amd64] https://download.docker.com/linux/debian jessie stable
Et mettre à jour les dépôts :
apt update
apt install docker-ce
docker run hello-world
Docker-compose est l’outil indispensable pour gérer vos images.
$ curl -L "https://github.com/docker/compose/releases/download/1.11.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
Et pour l’auto complétion…
curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
Voici un complément des bloqueurs de pub classique : le DNS.
# cd /etc/unbound/unbound.conf.d wget -O- https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts | grep '^0\.0\.0\.0' | awk '{print "local-zone: \""$2"\" redirect\nlocal-data: \""$2" A 0.0.0.0\""}' > adslist
On ajoute la prise en charge de cette liste de domaines à bloquer dans notre fichier de configuration d’Unbound :
#Ads blocking include: "/etc/unbound/unbound.conf.d/adslist"
Voilà ! Reste à relancer le service.
Sur ma station météo j’ai voulu implémenter un défilement pleine page (FullPage scrolling ou snap scroll). La difficulté était de charger et de rafraichir dynamiquement les éléments affichés. Il existe probablement des solutions plus élégantes. Mais celle-ci répond à mon besoin.
Pour le réaliser j’ai utilisé angular-snapscroll couplé à ses dépendances.
<div ng-controller="SnapCtrl as snapCtrl"> <div ng-init="snapIndex=0" snapscroll="" fit-window-height="" snap-index="snapIndex" ng-swipe-up="snapIndex=snapIndex+1" ng-swipe-down="snapIndex=snapIndex-1" before-snap="snapCtrl.beforeSnap(snapIndex)"> <div class="container"> vue 1 </div> <div class="container"> vue 2 </div> </div> </div>
Je maintiens un index qui sera récupéré par mon contrôleur. Voici le code, pour le moment, qui affiche l’index :
'use strict'; /** * @ngdoc function * @name App.controller:SnapCtrl * @description * # SnapCtrl * Controller of fullPage Scrolling */ angular.module('App') .controller('SnapCtrl', function($window, $location, $state) { var vm = this; vm.beforeSnap = function(snapIndex) { console.log('snapping to', snapIndex); }; });
Pour le routage j’utilise ui.router et les vues multiples.
Nommage des vues :
<div ng-controller="SnapCtrl as snapCtrl"> <div ng-init="snapIndex=0" snapscroll="" fit-window-height="" snap-index="snapIndex" ng-swipe-up="snapIndex=snapIndex+1" ng-swipe-down="snapIndex=snapIndex-1" before-snap="snapCtrl.beforeSnap(snapIndex)"> <div class="container"> <div ui-view="vue1"></div> </div> <div class="container"> <div ui-view="vue2"></div> </div> </div> </div>
Maintenant passons au routage :
angular.module('App') .config(function($routeProvider) { $routeProvider .otherwise({ redirectTo: '/' }); }); angular.module('App') .config(function($stateProvider) { $stateProvider .state('vue1', { url: "/", views: { "vue1": { templateUrl: 'views/vue1.html' }, "vue2": { template: '' } } }) .state('vue2', { url: "/vue2", views: { "vue1": { template: '' }, "vue2": { templateUrl: 'views/vue2.html' } } }); });
On affiche donc les vues 1 et 2 en fonction de la position du scroll.
Voici donc le contrôleur qui va forcer la navigation.
'use strict'; /** * @ngdoc function * @name weathergFrontApp.controller:SnapCtrl * @description * # SnapCtrl * Controller of the App */ angular.module('App') .controller('SnapCtrl', function($window, $location, $state) { var vm = this; vm.sections = ['vue1', 'vue2']; //routes to load (vue1.html, etc) vm.beforeSnap = function(snapIndex) { console.log('snapping to', snapIndex); $state.go(vm.sections[snapIndex]); }; });
Documentation angular-snapscroll
https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
Afin de pouvoir automatiser le passage de l’environnement de développement à l’environnent déployé. J’ai utilisé quelques astuces afin de gagner du temps lors de la production de version.
La solution consiste à générer un fichier env.js contenant les variables de déploiement. C’est Grunt qui fera le travail de configuration.
npm install --save-dev
Dans un répertoire config, on placera le template. Ce template sera utilisé pour générer le fichier de configuration. Dans ce script on stockera les différentes variables dans comme variable d’environnements (window.__env).
/**** DO NOT MODIFY DIRECLTY - THIS FILE IS AUTO GENERATED ***/ 'use strict'; (function (window) { window.__env = window.__env || {}; {% constants.forEach(function (constant){ %} window.__env.{%- constant.name %}={%= constant.value %}; {% }) %} }(this));
Et les fichiers de configurations…
Pour le développement :
{ "APIEndpoint": { "protocol": null, "host": null, "port": null } }
Pour la production :
{ "APIEndpoint": { "protocol": "http", "host": "api.host.fr", "port": 80 } }
Maintenant nous allons configurer notre module. En chargeant les variables d’environnement (window.__env) .
/** * Configuration for module. */ 'use strict'; angular.module('MyModule') .constant('Config', { API: { useMocks: true, fakeDelay: 2000, protocol: window.__env.APIEndpoint.protocol || window.location.protocol .split(':')[0], host: window.__env.APIEndpoint.host || window.location.hostname, //port: String(window.location.port || 80), port: window.__env.APIEndpoint.port || 3000 } });
On n’oubliera pas d’inclure le fichier env.js à nos scripts.
On enregistre une tache ngConstant chargée de générer le fichier env.js
// Automatically load required Grunt tasks require('jit-grunt')(grunt, { useminPrepare: 'grunt-usemin', ngtemplates: 'grunt-angular-templates', cdnify: 'grunt-google-cdn', ngconstant: 'grunt-ng-constant' }); /* ... */ ngconstant: { options: { // Name of our Angular module with configuration data. name: 'env', // Place where we need to create new file with our config module. dest: '<%= yeoman.app %>/scripts/env.js', // This object will be merged to all config files. constants: 'config/default.json', // Template to create config module. template: grunt.file.read('config/env-template.ejs') }, // Environments development: { constants: 'config/development.json' }, production: { constants: 'config/production.json' } } /* ... */ grunt.registerTask('build', function(target) { var ngconstantTask = 'ngconstant:development'; if (target === 'production') { ngconstantTask = 'ngconstant:production'; } grunt.task.run([ ngconstantTask, 'clean:dist', 'wiredep', 'useminPrepare', 'concurrent:dist', 'postcss', 'ngtemplates', 'concat', 'ngAnnotate', 'copy:dist', 'cdnify', 'cssmin', 'uglify', 'filerev', 'usemin', 'htmlmin' ]); }); grunt.registerTask('default', [ 'newer:jshint', 'newer:jscs', 'test', 'build' ]);
http://www.jvandemo.com/how-to-configure-your-angularjs-application-using-environment-variables/
http://cayugasoft.com/configuring-multiple-environments-angular-js-using-grunt-ng-constant/
Pour lancer une application sur l’hôte SSH :
Il suffit d’exécuter export DISPLAY=:id#
dans la session SSH.
toto@pc:~$ ssh testSSH@myServer toto@pc:~$ export DISPLAY=:0 toto@pc:~$ gedit
ssh testSSH@myServer "DISPLAY=:0 nohup gedit"
Pour l’affichage en root
export XAUTHORITY=/home/user/.Xauthority
Lors de mes tests de station météo j’ai pu constater qu’au bout que quelques jours la station ne répondais plus. Diagnostique, plus de réseau wifi. J’ai donc fouiner pour dénicher ce script.
#!/bin/bash # L'adresse IP du serveur que vous voulez pinger (8.8.8.8 est un serveur DNS public de Google) SERVER=8.8.8.8 # Envoyer seulement 2 pings, et envoyer la sortie vers /dev/null ping -c2 ${SERVER} > /dev/null # Si le code retour du ping ($?) est différent de 0 (qui correspond à une erreur) if [ $? != 0 ] then # Restart the wireless interface # Relancer l'interface wifi ifdown --force wlan0 ifup wlan0 fi
A placer dans un fichier a rendre exécutable :
sudo chmod +x /usr/local/bin/wifi_rebooter.sh
Ajouter la tache cron
suivante en éditant le fichier /etc/crontab
*/5 * * * * root /usr/local/bin/wifi_rebooter.sh
Sources :
http://www.domopi.eu/reconnecter-automatiquement-votre-raspberry-pi-au-wifi/
Pour compléter l’article sur la manière de créer un service sous Debian. Voici comment créer un service à partir d’une application NodeJS.
J’utilise forever. Pour l’installer, rien de plus simple avec NPM.
npm install -g forever
Je crée un répertoire dans lequel forever viendra écrire ses fichiers PID.
mkdir /var/run/forever
Voici maintenant le fichier de service :
#!/bin/sh # configure env export PATH=$PATH:/usr/local/bin export NODE_PATH=$NODE_PATH:/usr/local/lib/node_modules export SERVER_PORT=80 export SERVER_IFACE='0.0.0.0' # Chemin vers l'application APP_DIR=/var/app case "$1" in start) #exec forever --sourceDir=$APP_DIR -p /var/run/forever start -c "npm start" exec forever --sourceDir=$APP_DIR -p /var/run/forever start bin/www $APP_DIR ;; stop) exec forever stop --sourceDir=$APP_DIR bin/www ;; esac exit 0
Sources :
https://thomashunter.name/blog/running-a-node-js-process-on-debian-as-an-init-d-service