3852 lines
278 KiB
HTML
3852 lines
278 KiB
HTML
|
<!DOCTYPE html><html lang="fr">
|
|||
|
<head><meta charset="utf-8">
|
|||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>vps591606 Debian 9 - Yunohost - cinay.xyz (INACTIF) - YannStatic</title>
|
|||
|
|
|||
|
<meta name="description" content="Yunohost Debian Stretch cinay.xyz">
|
|||
|
<link rel="canonical" href="https://static.rnmkcy.eu/2018/12/21/vps591606_debian_9_yunohost_cinay.xyz.html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
|
|||
|
|
|||
|
<!-- - include head/favicon.html - -->
|
|||
|
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
|
|||
|
<!-- end custom head snippets --><script>(function() {
|
|||
|
window.isArray = function(val) {
|
|||
|
return Object.prototype.toString.call(val) === '[object Array]';
|
|||
|
};
|
|||
|
window.isString = function(val) {
|
|||
|
return typeof val === 'string';
|
|||
|
};
|
|||
|
|
|||
|
window.hasEvent = function(event) {
|
|||
|
return 'on'.concat(event) in window.document;
|
|||
|
};
|
|||
|
|
|||
|
window.isOverallScroller = function(node) {
|
|||
|
return node === document.documentElement || node === document.body || node === window;
|
|||
|
};
|
|||
|
|
|||
|
window.isFormElement = function(node) {
|
|||
|
var tagName = node.tagName;
|
|||
|
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
|
|||
|
};
|
|||
|
|
|||
|
window.pageLoad = (function () {
|
|||
|
var loaded = false, cbs = [];
|
|||
|
window.addEventListener('load', function () {
|
|||
|
var i;
|
|||
|
loaded = true;
|
|||
|
if (cbs.length > 0) {
|
|||
|
for (i = 0; i < cbs.length; i++) {
|
|||
|
cbs[i]();
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
return {
|
|||
|
then: function(cb) {
|
|||
|
cb && (loaded ? cb() : (cbs.push(cb)));
|
|||
|
}
|
|||
|
};
|
|||
|
})();
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
window.throttle = function(func, wait) {
|
|||
|
var args, result, thisArg, timeoutId, lastCalled = 0;
|
|||
|
|
|||
|
function trailingCall() {
|
|||
|
lastCalled = new Date;
|
|||
|
timeoutId = null;
|
|||
|
result = func.apply(thisArg, args);
|
|||
|
}
|
|||
|
return function() {
|
|||
|
var now = new Date,
|
|||
|
remaining = wait - (now - lastCalled);
|
|||
|
|
|||
|
args = arguments;
|
|||
|
thisArg = this;
|
|||
|
|
|||
|
if (remaining <= 0) {
|
|||
|
clearTimeout(timeoutId);
|
|||
|
timeoutId = null;
|
|||
|
lastCalled = now;
|
|||
|
result = func.apply(thisArg, args);
|
|||
|
} else if (!timeoutId) {
|
|||
|
timeoutId = setTimeout(trailingCall, remaining);
|
|||
|
}
|
|||
|
return result;
|
|||
|
};
|
|||
|
};
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var Set = (function() {
|
|||
|
var add = function(item) {
|
|||
|
var i, data = this._data;
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
if (data[i] === item) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
this.size ++;
|
|||
|
data.push(item);
|
|||
|
return data;
|
|||
|
};
|
|||
|
|
|||
|
var Set = function(data) {
|
|||
|
this.size = 0;
|
|||
|
this._data = [];
|
|||
|
var i;
|
|||
|
if (data.length > 0) {
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
add.call(this, data[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
Set.prototype.add = add;
|
|||
|
Set.prototype.get = function(index) { return this._data[index]; };
|
|||
|
Set.prototype.has = function(item) {
|
|||
|
var i, data = this._data;
|
|||
|
for (i = 0; i < data.length; i++) {
|
|||
|
if (this.get(i) === item) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
};
|
|||
|
Set.prototype.is = function(map) {
|
|||
|
if (map._data.length !== this._data.length) { return false; }
|
|||
|
var i, j, flag, tData = this._data, mData = map._data;
|
|||
|
for (i = 0; i < tData.length; i++) {
|
|||
|
for (flag = false, j = 0; j < mData.length; j++) {
|
|||
|
if (tData[i] === mData[j]) {
|
|||
|
flag = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!flag) { return false; }
|
|||
|
}
|
|||
|
return true;
|
|||
|
};
|
|||
|
Set.prototype.values = function() {
|
|||
|
return this._data;
|
|||
|
};
|
|||
|
return Set;
|
|||
|
})();
|
|||
|
|
|||
|
window.Lazyload = (function(doc) {
|
|||
|
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
|
|||
|
var createNode = function(name, attrs) {
|
|||
|
var node = doc.createElement(name), attr;
|
|||
|
for (attr in attrs) {
|
|||
|
if (attrs.hasOwnProperty(attr)) {
|
|||
|
node.setAttribute(attr, attrs[attr]);
|
|||
|
}
|
|||
|
}
|
|||
|
return node;
|
|||
|
};
|
|||
|
var end = function(type, url) {
|
|||
|
var s, q, qi, cbs, i, j, cur, val, flag;
|
|||
|
if (type === 'js' || type ==='css') {
|
|||
|
s = sources[type], q = queue[type];
|
|||
|
s[url] = true;
|
|||
|
for (i = 0; i < q.length; i++) {
|
|||
|
cur = q[i];
|
|||
|
if (cur.urls.has(url)) {
|
|||
|
qi = cur, val = qi.urls.values();
|
|||
|
qi && (cbs = qi.callbacks);
|
|||
|
for (flag = true, j = 0; j < val.length; j++) {
|
|||
|
cur = val[j];
|
|||
|
if (!s[cur]) {
|
|||
|
flag = false;
|
|||
|
}
|
|||
|
}
|
|||
|
if (flag && cbs && cbs.length > 0) {
|
|||
|
for (j = 0; j < cbs.length; j++) {
|
|||
|
cbs[j].call(context);
|
|||
|
}
|
|||
|
qi.load = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
var load = function(type, urls, callback) {
|
|||
|
var s, q, qi, node, i, cur,
|
|||
|
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
|
|||
|
if (type === 'js' || type ==='css') {
|
|||
|
s = sources[type], q = queue[type];
|
|||
|
for (i = 0; i < q.length; i++) {
|
|||
|
cur = q[i];
|
|||
|
if (_urls.is(cur.urls)) {
|
|||
|
qi = cur;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
val = _urls.values();
|
|||
|
if (qi) {
|
|||
|
callback && (qi.load || qi.callbacks.push(callback));
|
|||
|
callback && (qi.load && callback());
|
|||
|
} else {
|
|||
|
q.push({
|
|||
|
urls: _urls,
|
|||
|
callbacks: callback ? [callback] : [],
|
|||
|
load: false
|
|||
|
});
|
|||
|
for (i = 0; i < val.length; i++) {
|
|||
|
node = null, url = val[i];
|
|||
|
if (s[url] === undefined) {
|
|||
|
(type === 'js' ) && (node = createNode('script', { src: url }));
|
|||
|
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
|
|||
|
if (node) {
|
|||
|
node.onload = (function(type, url) {
|
|||
|
return function() {
|
|||
|
end(type, url);
|
|||
|
};
|
|||
|
})(type, url);
|
|||
|
(doc.head || doc.body).appendChild(node);
|
|||
|
s[url] = false;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
return {
|
|||
|
js: function(url, callback) {
|
|||
|
load('js', url, callback);
|
|||
|
},
|
|||
|
css: function(url, callback) {
|
|||
|
load('css', url, callback);
|
|||
|
}
|
|||
|
};
|
|||
|
})(this.document);
|
|||
|
})();
|
|||
|
</script><script>
|
|||
|
(function() {
|
|||
|
var TEXT_VARIABLES = {
|
|||
|
version: '2.2.6',
|
|||
|
sources: {
|
|||
|
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
|
|||
|
jquery: '/assets/js/jquery.min.js',
|
|||
|
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
|
|||
|
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
|
|||
|
gitalk: {
|
|||
|
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
|
|||
|
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
|
|||
|
},
|
|||
|
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
|
|||
|
},
|
|||
|
site: {
|
|||
|
toc: {
|
|||
|
selectors: 'h1,h2,h3'
|
|||
|
}
|
|||
|
},
|
|||
|
paths: {
|
|||
|
search_js: '/assets/search.js'
|
|||
|
}
|
|||
|
};
|
|||
|
window.TEXT_VARIABLES = TEXT_VARIABLES;
|
|||
|
})();
|
|||
|
</script>
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
<div class="root" data-is-touch="false">
|
|||
|
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
|
|||
|
|
|||
|
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
|
|||
|
<div class="header__title">
|
|||
|
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
|
|||
|
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
|
|||
|
<!-- Champ de recherche -->
|
|||
|
<div id="searchbox" class="search search--dark" style="visibility: visible">
|
|||
|
<div class="main">
|
|||
|
<div class="search__header"></div>
|
|||
|
<div class="search-bar">
|
|||
|
<div class="search-box js-search-box">
|
|||
|
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
|
|||
|
<input id="search-input" type="text" />
|
|||
|
<!-- <div class="search-box__icon-clear js-icon-clear">
|
|||
|
<a><i class="fas fa-times"></i></a>
|
|||
|
</div> -->
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!-- Script pointing to search-script.js -->
|
|||
|
<script>/*!
|
|||
|
* Simple-Jekyll-Search
|
|||
|
* Copyright 2015-2020, Christian Fei
|
|||
|
* Licensed under the MIT License.
|
|||
|
*/
|
|||
|
|
|||
|
(function(){
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Templater_7 = {
|
|||
|
compile: compile,
|
|||
|
setOptions: setOptions
|
|||
|
}
|
|||
|
|
|||
|
const options = {}
|
|||
|
options.pattern = /\{(.*?)\}/g
|
|||
|
options.template = ''
|
|||
|
options.middleware = function () {}
|
|||
|
|
|||
|
function setOptions (_options) {
|
|||
|
options.pattern = _options.pattern || options.pattern
|
|||
|
options.template = _options.template || options.template
|
|||
|
if (typeof _options.middleware === 'function') {
|
|||
|
options.middleware = _options.middleware
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function compile (data) {
|
|||
|
return options.template.replace(options.pattern, function (match, prop) {
|
|||
|
const value = options.middleware(prop, data[prop], options.template)
|
|||
|
if (typeof value !== 'undefined') {
|
|||
|
return value
|
|||
|
}
|
|||
|
return data[prop] || match
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
'use strict';
|
|||
|
|
|||
|
function fuzzysearch (needle, haystack) {
|
|||
|
var tlen = haystack.length;
|
|||
|
var qlen = needle.length;
|
|||
|
if (qlen > tlen) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
if (qlen === tlen) {
|
|||
|
return needle === haystack;
|
|||
|
}
|
|||
|
outer: for (var i = 0, j = 0; i < qlen; i++) {
|
|||
|
var nch = needle.charCodeAt(i);
|
|||
|
while (j < tlen) {
|
|||
|
if (haystack.charCodeAt(j++) === nch) {
|
|||
|
continue outer;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
var _$fuzzysearch_1 = fuzzysearch;
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
|
|||
|
|
|||
|
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
|
|||
|
|
|||
|
function FuzzySearchStrategy () {
|
|||
|
this.matches = function (string, crit) {
|
|||
|
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
|
|||
|
|
|||
|
function LiteralSearchStrategy () {
|
|||
|
this.matches = function (str, crit) {
|
|||
|
if (!str) return false
|
|||
|
|
|||
|
str = str.trim().toLowerCase()
|
|||
|
crit = crit.trim().toLowerCase()
|
|||
|
|
|||
|
return crit.split(' ').filter(function (word) {
|
|||
|
return str.indexOf(word) >= 0
|
|||
|
}).length === crit.split(' ').length
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Repository_4 = {
|
|||
|
put: put,
|
|||
|
clear: clear,
|
|||
|
search: search,
|
|||
|
setOptions: __setOptions_4
|
|||
|
}
|
|||
|
|
|||
|
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
|
|||
|
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
|
|||
|
|
|||
|
function NoSort () {
|
|||
|
return 0
|
|||
|
}
|
|||
|
|
|||
|
const data = []
|
|||
|
let opt = {}
|
|||
|
|
|||
|
opt.fuzzy = false
|
|||
|
opt.limit = 10
|
|||
|
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = NoSort
|
|||
|
opt.exclude = []
|
|||
|
|
|||
|
function put (data) {
|
|||
|
if (isObject(data)) {
|
|||
|
return addObject(data)
|
|||
|
}
|
|||
|
if (isArray(data)) {
|
|||
|
return addArray(data)
|
|||
|
}
|
|||
|
return undefined
|
|||
|
}
|
|||
|
function clear () {
|
|||
|
data.length = 0
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function isObject (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
|
|||
|
}
|
|||
|
|
|||
|
function isArray (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
|
|||
|
}
|
|||
|
|
|||
|
function addObject (_data) {
|
|||
|
data.push(_data)
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function addArray (_data) {
|
|||
|
const added = []
|
|||
|
clear()
|
|||
|
for (let i = 0, len = _data.length; i < len; i++) {
|
|||
|
if (isObject(_data[i])) {
|
|||
|
added.push(addObject(_data[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
return added
|
|||
|
}
|
|||
|
|
|||
|
function search (crit) {
|
|||
|
if (!crit) {
|
|||
|
return []
|
|||
|
}
|
|||
|
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
|
|||
|
}
|
|||
|
|
|||
|
function __setOptions_4 (_opt) {
|
|||
|
opt = _opt || {}
|
|||
|
|
|||
|
opt.fuzzy = _opt.fuzzy || false
|
|||
|
opt.limit = _opt.limit || 10
|
|||
|
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = _opt.sort || NoSort
|
|||
|
opt.exclude = _opt.exclude || []
|
|||
|
}
|
|||
|
|
|||
|
function findMatches (data, crit, strategy, opt) {
|
|||
|
const matches = []
|
|||
|
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
|
|||
|
const match = findMatchesInObject(data[i], crit, strategy, opt)
|
|||
|
if (match) {
|
|||
|
matches.push(match)
|
|||
|
}
|
|||
|
}
|
|||
|
return matches
|
|||
|
}
|
|||
|
|
|||
|
function findMatchesInObject (obj, crit, strategy, opt) {
|
|||
|
for (const key in obj) {
|
|||
|
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
|
|||
|
return obj
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isExcluded (term, excludedTerms) {
|
|||
|
for (let i = 0, len = excludedTerms.length; i < len; i++) {
|
|||
|
const excludedTerm = excludedTerms[i]
|
|||
|
if (new RegExp(excludedTerm).test(term)) {
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
/* globals ActiveXObject:false */
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$JSONLoader_2 = {
|
|||
|
load: load
|
|||
|
}
|
|||
|
|
|||
|
function load (location, callback) {
|
|||
|
const xhr = getXHR()
|
|||
|
xhr.open('GET', location, true)
|
|||
|
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
|
|||
|
xhr.send()
|
|||
|
}
|
|||
|
|
|||
|
function createStateChangeListener (xhr, callback) {
|
|||
|
return function () {
|
|||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
|||
|
try {
|
|||
|
callback(null, JSON.parse(xhr.responseText))
|
|||
|
} catch (err) {
|
|||
|
callback(err, null)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getXHR () {
|
|||
|
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$OptionsValidator_3 = function OptionsValidator (params) {
|
|||
|
if (!validateParams(params)) {
|
|||
|
throw new Error('-- OptionsValidator: required options missing')
|
|||
|
}
|
|||
|
|
|||
|
if (!(this instanceof OptionsValidator)) {
|
|||
|
return new OptionsValidator(params)
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = params.required
|
|||
|
|
|||
|
this.getRequiredOptions = function () {
|
|||
|
return requiredOptions
|
|||
|
}
|
|||
|
|
|||
|
this.validate = function (parameters) {
|
|||
|
const errors = []
|
|||
|
requiredOptions.forEach(function (requiredOptionName) {
|
|||
|
if (typeof parameters[requiredOptionName] === 'undefined') {
|
|||
|
errors.push(requiredOptionName)
|
|||
|
}
|
|||
|
})
|
|||
|
return errors
|
|||
|
}
|
|||
|
|
|||
|
function validateParams (params) {
|
|||
|
if (!params) {
|
|||
|
return false
|
|||
|
}
|
|||
|
return typeof params.required !== 'undefined' && params.required instanceof Array
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$utils_9 = {
|
|||
|
merge: merge,
|
|||
|
isJSON: isJSON
|
|||
|
}
|
|||
|
|
|||
|
function merge (defaultParams, mergeParams) {
|
|||
|
const mergedOptions = {}
|
|||
|
for (const option in defaultParams) {
|
|||
|
mergedOptions[option] = defaultParams[option]
|
|||
|
if (typeof mergeParams[option] !== 'undefined') {
|
|||
|
mergedOptions[option] = mergeParams[option]
|
|||
|
}
|
|||
|
}
|
|||
|
return mergedOptions
|
|||
|
}
|
|||
|
|
|||
|
function isJSON (json) {
|
|||
|
try {
|
|||
|
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
} catch (err) {
|
|||
|
return false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var _$src_8 = {};
|
|||
|
(function (window) {
|
|||
|
'use strict'
|
|||
|
|
|||
|
let options = {
|
|||
|
searchInput: null,
|
|||
|
resultsContainer: null,
|
|||
|
json: [],
|
|||
|
success: Function.prototype,
|
|||
|
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
|
|||
|
templateMiddleware: Function.prototype,
|
|||
|
sortMiddleware: function () {
|
|||
|
return 0
|
|||
|
},
|
|||
|
noResultsText: 'No results found',
|
|||
|
limit: 10,
|
|||
|
fuzzy: false,
|
|||
|
debounceTime: null,
|
|||
|
exclude: []
|
|||
|
}
|
|||
|
|
|||
|
let debounceTimerHandle
|
|||
|
const debounce = function (func, delayMillis) {
|
|||
|
if (delayMillis) {
|
|||
|
clearTimeout(debounceTimerHandle)
|
|||
|
debounceTimerHandle = setTimeout(func, delayMillis)
|
|||
|
} else {
|
|||
|
func.call()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
|
|||
|
|
|||
|
/* removed: const _$Templater_7 = require('./Templater') */;
|
|||
|
/* removed: const _$Repository_4 = require('./Repository') */;
|
|||
|
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
|
|||
|
const optionsValidator = _$OptionsValidator_3({
|
|||
|
required: requiredOptions
|
|||
|
})
|
|||
|
/* removed: const _$utils_9 = require('./utils') */;
|
|||
|
|
|||
|
window.SimpleJekyllSearch = function (_options) {
|
|||
|
const errors = optionsValidator.validate(_options)
|
|||
|
if (errors.length > 0) {
|
|||
|
throwError('You must specify the following required options: ' + requiredOptions)
|
|||
|
}
|
|||
|
|
|||
|
options = _$utils_9.merge(options, _options)
|
|||
|
|
|||
|
_$Templater_7.setOptions({
|
|||
|
template: options.searchResultTemplate,
|
|||
|
middleware: options.templateMiddleware
|
|||
|
})
|
|||
|
|
|||
|
_$Repository_4.setOptions({
|
|||
|
fuzzy: options.fuzzy,
|
|||
|
limit: options.limit,
|
|||
|
sort: options.sortMiddleware,
|
|||
|
exclude: options.exclude
|
|||
|
})
|
|||
|
|
|||
|
if (_$utils_9.isJSON(options.json)) {
|
|||
|
initWithJSON(options.json)
|
|||
|
} else {
|
|||
|
initWithURL(options.json)
|
|||
|
}
|
|||
|
|
|||
|
const rv = {
|
|||
|
search: search
|
|||
|
}
|
|||
|
|
|||
|
typeof options.success === 'function' && options.success.call(rv)
|
|||
|
return rv
|
|||
|
}
|
|||
|
|
|||
|
function initWithJSON (json) {
|
|||
|
_$Repository_4.put(json)
|
|||
|
registerInput()
|
|||
|
}
|
|||
|
|
|||
|
function initWithURL (url) {
|
|||
|
_$JSONLoader_2.load(url, function (err, json) {
|
|||
|
if (err) {
|
|||
|
throwError('failed to get JSON (' + url + ')')
|
|||
|
}
|
|||
|
initWithJSON(json)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function emptyResultsContainer () {
|
|||
|
options.resultsContainer.innerHTML = ''
|
|||
|
}
|
|||
|
|
|||
|
function appendToResultsContainer (text) {
|
|||
|
options.resultsContainer.innerHTML += text
|
|||
|
}
|
|||
|
|
|||
|
function registerInput () {
|
|||
|
options.searchInput.addEventListener('input', function (e) {
|
|||
|
if (isWhitelistedKey(e.which)) {
|
|||
|
emptyResultsContainer()
|
|||
|
debounce(function () { search(e.target.value) }, options.debounceTime)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function search (query) {
|
|||
|
if (isValidQuery(query)) {
|
|||
|
emptyResultsContainer()
|
|||
|
render(_$Repository_4.search(query), query)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function render (results, query) {
|
|||
|
const len = results.length
|
|||
|
if (len === 0) {
|
|||
|
return appendToResultsContainer(options.noResultsText)
|
|||
|
}
|
|||
|
for (let i = 0; i < len; i++) {
|
|||
|
results[i].query = query
|
|||
|
appendToResultsContainer(_$Templater_7.compile(results[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isValidQuery (query) {
|
|||
|
return query && query.length > 0
|
|||
|
}
|
|||
|
|
|||
|
function isWhitelistedKey (key) {
|
|||
|
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
|
|||
|
}
|
|||
|
|
|||
|
function throwError (message) {
|
|||
|
throw new Error('SimpleJekyllSearch --- ' + message)
|
|||
|
}
|
|||
|
})(window)
|
|||
|
|
|||
|
}());
|
|||
|
</script>
|
|||
|
|
|||
|
<!-- Configuration -->
|
|||
|
<script>
|
|||
|
SimpleJekyllSearch({
|
|||
|
searchInput: document.getElementById('search-input'),
|
|||
|
resultsContainer: document.getElementById('results-container'),
|
|||
|
json: '/search.json',
|
|||
|
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date} {title}</a></li>'
|
|||
|
searchResultTemplate: '<li><a href="{url}">{date} {title}</a></li>'
|
|||
|
})
|
|||
|
</script>
|
|||
|
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
|
|||
|
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
|
|||
|
</nav></div>
|
|||
|
</header>
|
|||
|
|
|||
|
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
|
|||
|
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
|
|||
|
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">vps591606 Debian 9 - Yunohost - cinay.xyz (INACTIF)</h1></header></div><meta itemprop="headline" content="vps591606 Debian 9 - Yunohost - cinay.xyz (INACTIF)"><div class="article__info clearfix"><ul class="left-col menu"><li>
|
|||
|
<a class="button button--secondary button--pill button--sm"
|
|||
|
href="/archive.html?tag=yunohost">yunohost</a>
|
|||
|
</li></ul><ul class="right-col menu"><li>
|
|||
|
<i class="far fa-calendar-alt"></i> <span title="Création" style="color:#FF00FF">21 déc. 2018</span>
|
|||
|
|
|||
|
<span title="Modification" style="color:#00FF7F">21 juil. 2020</span></li></ul></div><meta itemprop="datePublished" content="2020-07-21T00:00:00+02:00">
|
|||
|
<meta itemprop="keywords" content="yunohost"><div class="js-article-content">
|
|||
|
<div class="layout--article"><!-- start custom article top snippet -->
|
|||
|
<style>
|
|||
|
#myBtn {
|
|||
|
display: none;
|
|||
|
position: fixed;
|
|||
|
bottom: 10px;
|
|||
|
right: 10px;
|
|||
|
z-index: 99;
|
|||
|
font-size: 12px;
|
|||
|
font-weight: bold;
|
|||
|
border: none;
|
|||
|
outline: none;
|
|||
|
background-color: white;
|
|||
|
color: black;
|
|||
|
cursor: pointer;
|
|||
|
padding: 5px;
|
|||
|
border-radius: 4px;
|
|||
|
}
|
|||
|
|
|||
|
#myBtn:hover {
|
|||
|
background-color: #555;
|
|||
|
}
|
|||
|
</style>
|
|||
|
|
|||
|
<button onclick="topFunction()" id="myBtn" title="Haut de page">⇧</button>
|
|||
|
|
|||
|
<script>
|
|||
|
//Get the button
|
|||
|
var mybutton = document.getElementById("myBtn");
|
|||
|
|
|||
|
// When the user scrolls down 20px from the top of the document, show the button
|
|||
|
window.onscroll = function() {scrollFunction()};
|
|||
|
|
|||
|
function scrollFunction() {
|
|||
|
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
|
|||
|
mybutton.style.display = "block";
|
|||
|
} else {
|
|||
|
mybutton.style.display = "none";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// When the user clicks on the button, scroll to the top of the document
|
|||
|
function topFunction() {
|
|||
|
document.body.scrollTop = 0;
|
|||
|
document.documentElement.scrollTop = 0;
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
|
|||
|
<!-- end custom article top snippet -->
|
|||
|
<div class="article__content" itemprop="articleBody"><details>
|
|||
|
<summary><b>Afficher/cacher Sommaire</b></summary>
|
|||
|
<!-- affichage sommaire -->
|
|||
|
<div class="toc-aside js-toc-root"></div>
|
|||
|
</details><h2 id="yunohost-debian-stretch-cinayxyz">Yunohost Debian Stretch cinay.xyz</h2>
|
|||
|
|
|||
|
<h3 id="vps-kvm-ovh">VPS-KVM OVH</h3>
|
|||
|
|
|||
|
<p><img src="/images/OVH-320px-Logo.png" alt="" width="100px" /><br />
|
|||
|
VPS 2018 SSD 3</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>2 vCores</li>
|
|||
|
<li>8Go Ram</li>
|
|||
|
<li>80Go SSD</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Livraison : vps591606 51.75.120.106</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Domaine : cinay.xyz</li>
|
|||
|
<li>IPv4 du serveur : 51.75.120.106</li>
|
|||
|
<li>IPv6 du serveur : 2001:41d0:0305:2100:0:0:0:4dc0 (2001:41d0:305:2100::4dc0)</li>
|
|||
|
<li>IPV6 gateway : 2001:41d0:0305:2100:0:0:0:1 (2001:41d0:305:2100::1)</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="debian-stretch">Debian Stretch</h3>
|
|||
|
|
|||
|
<p><img src="/images/debian-stretch-logo.png" alt="Debian 9" /></p>
|
|||
|
|
|||
|
<p>Connexion SSH sur “VPS 2018 SSD 3 (2 vCores/8GoRam/80GoSSD)”</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh root@51.75.120.106
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Modification du réseau, ajout IPV6</strong><br />
|
|||
|
Sur le VPS OVH il faut désactiver l’initialisation réseau par le cloud</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># To disable cloud-init's network configuration capabilities, write a file
|
|||
|
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
|
|||
|
# network: {config: disabled}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Création du fichier <strong>/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg</strong> en mode su</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "network: {config: disabled}" > /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier le fichier <strong>/etc/network/interfaces</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># This file describes the network interfaces available on your system
|
|||
|
# and how to activate them. For more information, see interfaces(5).
|
|||
|
|
|||
|
source /etc/network/interfaces.d/*
|
|||
|
|
|||
|
auto lo
|
|||
|
iface lo inet loopback
|
|||
|
|
|||
|
auto ens3
|
|||
|
iface ens3 inet dhcp
|
|||
|
iface ens3 inet6 static
|
|||
|
address 2001:41d0:0305:2100:0:0:0:4dc0
|
|||
|
netmask 128
|
|||
|
post-up /sbin/ip -6 route add 2001:41d0:0305:2100:0:0:0:1 dev ens3
|
|||
|
post-up /sbin/ip -6 route add default via 2001:41d0:0305:2100:0:0:0:1 dev ens3
|
|||
|
pre-down /sbin/ip -6 route del default via 2001:41d0:0305:2100:0:0:0:1 dev ens3
|
|||
|
pre-down /sbin/ip -6 route del 2001:41d0:0305:2100:0:0:0:1 dev ens3
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Mise à jour de la distribution debian stretch</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update && apt -y upgrade
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Redémarrer la machine <code class="language-plaintext highlighter-rouge">systemctl reboot</code> pour la prise en compte des modifications du réseau</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>Connexion SSH sur “VPS 2018 SSD 3 (2 vCores/8GoRam/80GoSSD)”</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh root@51.75.120.106
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier le réseau <code class="language-plaintext highlighter-rouge">ip addr</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
|
|||
|
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
|||
|
inet 127.0.0.1/8 scope host lo
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
inet6 ::1/128 scope host
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
|
|||
|
link/ether fa:16:3e:07:c2:34 brd ff:ff:ff:ff:ff:ff
|
|||
|
inet 51.75.120.106/32 brd 51.75.120.106 scope global ens3
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
inet6 2001:41d0:305:2100::4dc0/128 scope global
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
inet6 fe80::f816:3eff:fe07:c234/64 scope link
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="yunohost">Yunohost</h2>
|
|||
|
|
|||
|
<p><img src="/images/yunohost.png" alt="Yunohost" width="50px" /></p>
|
|||
|
|
|||
|
<h3 id="installation-yunohost">Installation Yunohost</h3>
|
|||
|
|
|||
|
<p>Lancer le bash et patienter</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bash <(wget -q -O- https://install.yunohost.org/)
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Valider la “post-installation” ou lancer</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost tools postinstall
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Main domain: cinay.xyz <br />
|
|||
|
Mot de passe administrateur</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Success! YunoHost has been configured
|
|||
|
Warning: The post-install is finished but YunoHost needs at least one user to work correctly, you should add one using 'yunohost user create' or the admin interface.
|
|||
|
[INFO] Installation logs are available in /var/log/yunohost-installation_20181203_070221.log
|
|||
|
[ OK ] YunoHost installation completed !
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="créer-un-utilisateur">Créer un utilisateur</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost user create yannick
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Mot de passe d'administration :
|
|||
|
Prénom : yannick
|
|||
|
Nom : meunier
|
|||
|
Adresse courriel : yannick@cinay.xyz
|
|||
|
Mot de passe :
|
|||
|
Confirmez : mot de passe :
|
|||
|
Création du répertoire « /home/yannick ».
|
|||
|
Succès ! La configuration de SSOwat a été générée
|
|||
|
Succès ! L'utilisateur a été créé
|
|||
|
fullname: yannick meunier
|
|||
|
mail: yannick@cinay.xyz
|
|||
|
username: yannick
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="installation-des-certificats">Installation des certificats</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain cert-install
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Info: Now attempting install of certificate for domain cinay.xyz!
|
|||
|
Succès ! La configuration de SSOwat a été générée
|
|||
|
Succès ! La configuration a été mise à jour pour le service « dnsmasq »
|
|||
|
Info: Parsing account key...
|
|||
|
Info: Parsing CSR...
|
|||
|
Info: Registering account...
|
|||
|
Info: Registered!
|
|||
|
Info: Verifying cinay.xyz...
|
|||
|
Info: cinay.xyz verified!
|
|||
|
Info: Signing certificate...
|
|||
|
Info: Certificate signed!
|
|||
|
Succès ! Installation avec succès d’un certificat Let’s Encrypt pour le domaine cinay.xyz !
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="administration-yunohost">Administration yunohost</h3>
|
|||
|
|
|||
|
<p>Connexion administrateur yunohost <a href="https://cinay.xyz/yunohost/admin">https://cinay.xyz/yunohost/admin</a><br />
|
|||
|
Vérifier le status des services <a href="https://cinay.xyz/yunohost/admin/#/services">https://cinay.xyz/yunohost/admin/#/services</a><br />
|
|||
|
Récupérer les paramètres DNS du domaine cinay.xyz <a href="https://cinay.xyz/yunohost/admin/#/domains/cinay.xyz/dns">https://cinay.xyz/yunohost/admin/#/domains/cinay.xyz/dns</a></p>
|
|||
|
|
|||
|
<h3 id="administration-ovh-dns-et-vps">Administration OVH (DNS et VPS)</h3>
|
|||
|
|
|||
|
<p>Se connecter sur le manager OVH</p>
|
|||
|
|
|||
|
<p>Modifier le reverse DNS du VPS vps591606.ovh.net (IPV4 er IPV6) : cinay.xyz<br />
|
|||
|
Modifier la configuration DNS du domaine cinay.xyz</p>
|
|||
|
|
|||
|
<p><img src="/images/dns-logo.png" alt="DNS" /></p>
|
|||
|
|
|||
|
<p>Se connecter en administrateur sur le site <strong>cinay.xyz</strong><br />
|
|||
|
Domaines → cinay.xyz → Configuration DNS # pour récupérer les paramètres<br />
|
|||
|
Modifier la DNS du domaine cinay.xyz :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$TTL 3600
|
|||
|
@ IN SOA dns112.ovh.net. tech.ovh.net. (2018092426 86400 3600 3600000 300)
|
|||
|
3600 IN NS dns112.ovh.net.
|
|||
|
3600 IN NS ns112.ovh.net.
|
|||
|
3600 IN MX 10 cinay.xyz.
|
|||
|
3600 IN A 51.75.120.106
|
|||
|
3600 IN AAAA 2001:41d0:305:2100::4dc0
|
|||
|
600 IN TXT "v=spf1 a mx ip4:51.75.120.106 ip6:2001:41d0:305:2100::4dc0 -all"
|
|||
|
* 3600 IN CNAME cinay.xyz.
|
|||
|
_dmarc IN TXT ( "v=DMARC1; p=none;" )
|
|||
|
_xmpp-client._tcp 3600 IN SRV 0 5 5222 cinay.xyz.
|
|||
|
_xmpp-server._tcp 3600 IN SRV 0 5 5269 cinay.xyz.
|
|||
|
mail._domainkey 3600 IN TXT ( "v=DKIM1; k=rsa; h=sha256; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOltTHam7WsBs1Fn26v7hSqe4bkNsruffIpinULglGcLHR8H0Cbks1jPuAZKuKLH1J7KxwelJ9F17mNqCuVDyPwGx1qLT8aEs3vD6L8tn9Aow1b2hEr2HQR6B6Ad90QYliI1BIVjrTjCpJyWYv3PUNow4QnUw/UhxX2bEK19apUwIDAQAB" )
|
|||
|
muc 3600 IN CNAME cinay.xyz.
|
|||
|
pubsub 3600 IN CNAME cinay.xyz.
|
|||
|
vjud 3600 IN CNAME cinay.xyz.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="sécurité">Sécurité</h3>
|
|||
|
|
|||
|
<h4 id="openssh-avec-clés">OpenSSH avec clés</h4>
|
|||
|
|
|||
|
<p><img src="/images/ssh_logo1.png" alt="OpenSSH" /></p>
|
|||
|
|
|||
|
<p><strong>Créer un utilisateur debian</strong><br />
|
|||
|
Il faut un utilisateur debian non ldap pour les connexions ssh</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>adduser debadm # création du home et saisie mot de passe
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Visudo pour les accès root via utilisateur debadm</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "debadm ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Poste local</strong><br />
|
|||
|
Génération d’une paire de clés</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh-keygen -f ~/.ssh/kvm-vps591606 -t ed25519 -o -a 100
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le déploiement de la clé publiques .pub</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh-copy-id -i ~/.ssh/kvm-vps591606.pub debadm@51.75.120.106
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Serveur distant</strong></p>
|
|||
|
|
|||
|
<p>Se connecter au serveur distant depuis le poste local avec utilisateur debian</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh debadm@cinay.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>La clé publique est ajoutée au fichier distant <strong>/home/debadm/.ssh/authorized_keys</strong> du serveur <br />
|
|||
|
Autre possibilité :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir /home/debadm/.ssh # créer un dossier .ssh
|
|||
|
nano /home/debadm/.ssh/authorized_keys # Coller le contenu de la clé publique kvm-vps591606.pub
|
|||
|
chmod 600 /home/debadm/.ssh/authorized_keys # droits utilisateur
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Utiliser la clé publique</strong></p>
|
|||
|
|
|||
|
<p>Fichier <strong>/etc/ssh/sshd_config</strong> sur le serveur distant, liste des paramètres qui sont modifiés</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Port 55031
|
|||
|
PermitRootLogin no
|
|||
|
PasswordAuthentication no
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>On peut également modifier le port de connexion SSH<br />
|
|||
|
Exemple remplacer port 22 par port 55031 :<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">Port 55031</code> # dans le fichier <strong>/etc/ssh/sshd_config</strong><br />
|
|||
|
NE PAS OUBLIER DE MODIFIER LE PAREFEU (FIREWALL) YUNOHOST :<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">yunohost firewall disallow TCP 22</code> # désactiver le port 22<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">yunohost firewall allow TCP 55031</code> # activer le port 55031</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>Recharger le serveur ssh</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart sshd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Test de la connexion ssh par clé depuis le poste local</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh -i ~/.ssh/kvm-vps591606 debadm@51.75.120.106 # port 22
|
|||
|
ssh -p 55031 -i ~/.ssh/kvm-vps591606 debadm@51.75.120.106 # port 55031
|
|||
|
ssh -p 55031 -i ~/.ssh/kvm-vps591606 debadm@cinay.xyz # port 55031 et DNS OK/Domaine
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Affichage à la connexion ssh</strong></p>
|
|||
|
|
|||
|
<p>Exécuter un fichier <em>utilisateur</em> nommé <strong>$HOME/.ssh/rc</strong> si <em>présent (NON PRESENT)</em><br />
|
|||
|
Pour <em>tous les utilisateurs</em> exécuter un fichier nommé <strong>/etc/ssh/sshrc</strong> si <em>présent (NON PRESENT)</em><br />
|
|||
|
Installer les utilitaires <em>curl jq figlet tmux</em></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install curl jq figlet
|
|||
|
sudo apt install tmux p7zip # outils supplémentaires
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer le fichier <strong>~/ssh_rc_bash</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
|
|||
|
|
|||
|
#clear
|
|||
|
PROCCOUNT=`ps -Afl | wc -l` # nombre de lignes
|
|||
|
PROCCOUNT=`expr $PROCCOUNT - 5` # on ote les non concernées
|
|||
|
GROUPZ=`users`
|
|||
|
ipinfo=$(curl -s ipinfo.io) # info localisation format json
|
|||
|
publicip=$(echo $ipinfo | jq -r '.ip') # extraction des données , installer préalablement "jq"
|
|||
|
ville=$(echo $ipinfo | jq -r '.city')
|
|||
|
pays=$(echo $ipinfo | jq -r '.country')
|
|||
|
cpuname=`cat /proc/cpuinfo |grep 'model name' | cut -d: -f2 | sed -n 1p`
|
|||
|
iplink=`ip link show |grep -m 1 "2:" | awk '{print $2}' | cut -d: -f1`
|
|||
|
|
|||
|
echo "\033[0m\033[1;31m"
|
|||
|
figlet "`hostname --fqdn`"
|
|||
|
echo "\033[0m
|
|||
|
\033[1;35m \033[1;37mHostname \033[1;35m= \033[1;32m`hostname`
|
|||
|
\033[1;35m \033[1;37mWired IpV4 \033[1;35m= \033[1;32m`ip addr show $iplink | grep 'inet\b' | awk '{print $2}' | cut -d/ -f1`
|
|||
|
\033[1;35m \033[1;37mWired IpV6 \033[1;35m= \033[1;32m`ip addr show $iplink | grep -E 'inet6' |grep -E 'scope link' | awk '{print $2}' | cut -d/ -f1`
|
|||
|
\033[1;35m \033[1;37mKernel \033[1;35m= \033[1;32m`uname -r`
|
|||
|
\033[1;35m \033[1;37mDebian \033[1;35m= \033[1;32m`cat /etc/debian_version`
|
|||
|
\033[1;35m \033[1;37mUptime \033[1;35m= \033[1;32m`uptime | sed 's/.*up ([^,]*), .*/1/' | sed -e 's/^[ \t]*//'`
|
|||
|
\033[1;35m \033[1;37mCPU \033[1;35m= \033[1;32m`echo $cpuname`
|
|||
|
\033[1;35m \033[1;37mMemory Use \033[1;35m= \033[1;32m`free -m | awk 'NR==2{printf "%s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }'`
|
|||
|
\033[1;35m \033[1;37mUsername \033[1;35m= \033[1;32m`whoami`
|
|||
|
\033[1;35m \033[1;37mSessions \033[1;35m= \033[1;32m`who | grep $USER | wc -l`
|
|||
|
\033[1;35m \033[1;37mPublic IpV4 \033[1;35m= \033[1;32m`echo $publicip`
|
|||
|
\033[1;35m \033[1;37mPublic IpV6 \033[1;35m= \033[1;32m`ip addr show $iplink | grep -m 1 'inet6\b' | awk '{print $2}' | cut -d/ -f1`
|
|||
|
\033[0m"
|
|||
|
df -h /
|
|||
|
#curl fr.wttr.in/$ville?0
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le rendre exécutable</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod +x ~/ssh_rc_bash
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Recréer motd</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm /etc/motd && sudo nano /etc/motd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ___ ___ _ __ __ __
|
|||
|
__ __ _ __ ___| __|/ _ \/ | / / / \ / /
|
|||
|
\ V /| '_ \(_-<|__ \\_, /| |/ _ \| () |/ _ \
|
|||
|
\_/ | .__//__/|___/ /_/ |_|\___/ \__/ \___/
|
|||
|
|_|
|
|||
|
__ (_) _ _ __ _ _ _ __ __ _ _ ___
|
|||
|
/ _|| || ' \ / _` || || | _ \ \ /| || ||_ /
|
|||
|
\__||_||_||_|\__,_| \_, |(_)/_\_\ \_, |/__|
|
|||
|
|__/ |__/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Déconnexion puis connexion</p>
|
|||
|
|
|||
|
<h4 id="désactivation-de-lapi-yunohost">Désactivation de l’API YunoHost</h4>
|
|||
|
|
|||
|
<p>YunoHost est administrable via une API HTTP, servie sur le port 6787 par défaut (seulement sur localhost). Elle permet d’administrer une grande partie de votre serveur, et peut donc être utilisée à des fins malveillantes. La meilleure chose à faire si vous êtes habitués aux lignes de commande est de désactiver le service yunohost-api, et utiliser la ligne de commande en SSH.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl disable yunohost-api
|
|||
|
sudo systemctl stop yunohost-api
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="applications-yunohost">Applications Yunohost</h2>
|
|||
|
|
|||
|
<h3 id="nextcloud">Nextcloud</h3>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud_logo.png" alt="Nextcloud" /><br />
|
|||
|
Installer <strong>Nextcloud</strong> avec l’administrateur web yunohost <br />
|
|||
|
<em>Accéder au dossier personnel des utilisateurs depuis Nextcloud</em></p>
|
|||
|
|
|||
|
<h3 id="transmission">Transmission</h3>
|
|||
|
|
|||
|
<p><img src="/images/transmission-logo.png" alt="Transmission" /><br />
|
|||
|
Installer <strong>Transmission</strong> avec l’administrateur web yunohost</p>
|
|||
|
|
|||
|
<h3 id="tiny-tiny-rss">Tiny Tiny RSS</h3>
|
|||
|
|
|||
|
<p><img src="/images/ttrss-logo.png" alt="Tiny Tiny RSS" /><br />
|
|||
|
Installer <strong>Tiny Tiny RSS</strong> avec l’administrateur web yunohost <br />
|
|||
|
Thèmes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
git clone https://github.com/levito/tt-rss-feedly-theme.git
|
|||
|
cp -r tt-rss-feedly-theme/feedly* /var/www/ttrss/themes.local/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="gitea-publique-giteacinayxyz">Gitea (publique gitea.cinay.xyz)</h3>
|
|||
|
|
|||
|
<p><img src="/images/gitea-logo.png" alt="Gitea" /></p>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Ajout domaine <strong>gitea.cinay.xz</strong></li>
|
|||
|
<li>Certificats Let’s Encrypt pour le domaine</li>
|
|||
|
<li>Installer l’application <strong>Gitea</strong>
|
|||
|
<ul>
|
|||
|
<li>domaine : gitea.cinay.xyz</li>
|
|||
|
<li>Chemin : /</li>
|
|||
|
<li>Administrateur : yannick</li>
|
|||
|
<li>Site publique : Oui</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<p><img src="/images/gitea-web.png" alt="gitea-web" width="400" /><br />
|
|||
|
<a href="https://gitea.cinay.xyz/">https://gitea.cinay.xyz/</a></p>
|
|||
|
|
|||
|
<h3 id="calibre-web-publique-calibrecinayxyz">Calibre-Web (publique calibre.cinay.xyz)</h3>
|
|||
|
|
|||
|
<p><img src="/images/Calibre_logo.png" alt="Calibre-web" /></p>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Ajout domaine <strong>calibre.cinay.xz</strong></li>
|
|||
|
<li>Certificats Let’s Encrypt pour le domaine</li>
|
|||
|
<li>Installer l’application <strong>Calibre-web</strong><br />
|
|||
|
<img src="/images/calibre-web-ynh.png" alt="calibre-web" width="300" /></li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<p>Emplacement de la base de donnée Calibre : <strong>/home/yunohost.multimedia/share/eBook/</strong><br />
|
|||
|
Copie dossier CalibreTechnique du serveur backup xoyaz.xyz → cinay.xyz</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
rsync -avz -e "ssh -p 55036 -i .ssh/OVZ-STORAGE-128 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress usernl@5.2.79.107:/home/usernl/backup/CalibreTechnique/* /home/yunohost.multimedia/share/eBook/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>En mode admin , il faut redémarrer calibre-web<br />
|
|||
|
Automatiser la synchronisation des dossiers</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>crontab -e # ajouter la ligne suivante en fin de fichier
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Synchroniser le dossier "CalibreTechnique" entre le serveur de backup distant xoyaz.xyz et le serveur local cinay.xyz
|
|||
|
15 01 * * * /usr/bin/rsync -avz -e "ssh -p 55036 -i .ssh/OVZ-STORAGE-128 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress usernl@5.2.79.107:/home/usernl/backup/CalibreTechnique/* /home/yunohost.multimedia/share/eBook/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><img src="/images/calibre-web.png" alt="calibre-web" width="400" /><br />
|
|||
|
<a href="https://calibre.cinay.xz">https://calibre.cinay.xz</a></p>
|
|||
|
|
|||
|
<h3 id="dokuwiki">Dokuwiki</h3>
|
|||
|
|
|||
|
<p><img src="/images/dokuwiki-logo.png" alt="Texte alternatif" /><br />
|
|||
|
Installer <strong>Dokuwiki</strong> avec l’administrateur web yunohost</p>
|
|||
|
|
|||
|
<p><strong>En cas de problème</strong></p>
|
|||
|
|
|||
|
<p>Le point le plus important et la prise en charge LDAP , le plugin <strong>LDAP Auth Plugin</strong> doit être actif (cas de transfert de dokuwiki ou après une mise à jour , perte de l’authentification LDAP !!!)<br />
|
|||
|
La configuration spécifique à LDAP dans le fichier <strong>/var/www/dokuwiki/conf/dokuwiki.php</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/* Authentication Settings */
|
|||
|
$conf['useacl'] = 1; //Use Access Control Lists to restrict access?
|
|||
|
$conf['openregister']= 0;
|
|||
|
$conf['autopasswd'] = 1; //autogenerate passwords and email them to user
|
|||
|
$conf['authtype'] = 'authldap'; //which authentication backend should be used
|
|||
|
$conf['passcrypt'] = 'sha1'; //Used crypt method (smd5,md5,sha1,ssha,crypt,mysql,my411)
|
|||
|
$conf['defaultgroup']= 'user'; //Default groups new Users are added to
|
|||
|
$conf['superuser'] = 'yannick'; //The admin can be user or @group or comma separated list user1,@group1,user2
|
|||
|
$conf['manager'] = 'yannick'; //The manager can be user or @group or comma separated list user1,@group1,user2
|
|||
|
$conf['profileconfirm'] = 1; //Require current password to confirm changes to user profile
|
|||
|
$conf['rememberme'] = 1; //Enable/disable remember me on login
|
|||
|
$conf['disableactions'] = ''; //comma separated list of actions to disable
|
|||
|
$conf['auth_security_timeout'] = 900; //time (seconds) auth data is considered valid, set to 0 to recheck on every page view
|
|||
|
$conf['securecookie'] = 1; //never send HTTPS cookies via HTTP
|
|||
|
$conf['remote'] = 0; //Enable/disable remote interfaces
|
|||
|
$conf['remoteuser'] = '!!not set !!'; //user/groups that have access to remote interface (comma separated)
|
|||
|
|
|||
|
/* LDAP Yunohost config */
|
|||
|
$conf['plugin']['authldap']['server'] = 'localhost';
|
|||
|
$conf['plugin']['authldap']['port'] = 389;
|
|||
|
$conf['plugin']['authldap']['version'] = 3;
|
|||
|
$conf['plugin']['authldap']['usertree'] = 'ou=users,dc=yunohost,dc=org';
|
|||
|
$conf['plugin']['authldap']['userfilter'] = '(&(uid=%{user})(objectClass=posixAccount))';
|
|||
|
# no groups
|
|||
|
#$conf['plugin']['authldap']['grouptree'] = 'ou=Group, dc=server, dc=tld';
|
|||
|
#$conf['plugin']['authldap']['groupfilter'] = '(&(objectClass=posixGroup)(|(gidNumber=%{gid})(memberUID=%{user})))';
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Structure et droits des dossiers dokuwiki</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@cinay:/home/debadm# ls -la /var/www/dokuwiki/
|
|||
|
total 124
|
|||
|
drwxr-xr-x 9 root root 4096 Nov 6 15:56 .
|
|||
|
drwxr-xr-x 7 root root 4096 Dec 3 09:30 ..
|
|||
|
drwxr-xr-x 2 root root 4096 May 3 2018 bin
|
|||
|
drwxr-xr-x 2 dokuwiki root 4096 Nov 6 15:57 conf
|
|||
|
-rw-r--r-- 1 root root 18092 May 3 2018 COPYING
|
|||
|
drwxr-x--- 12 dokuwiki root 4096 Nov 6 15:56 data
|
|||
|
drwxr-xr-x 2 root root 12288 Sep 5 07:21 doc
|
|||
|
-rw-r--r-- 1 root root 3547 Nov 6 15:56 doku.php
|
|||
|
-rw-r--r-- 1 root root 19141 May 3 2018 feed.php
|
|||
|
-rw-r--r-- 1 root root 1684 May 3 2018 .htaccess.dist
|
|||
|
drwxr-xr-x 9 dokuwiki root 4096 Nov 6 15:56 inc
|
|||
|
-rw-r--r-- 1 root root 2097 May 3 2018 index.php
|
|||
|
-rw-r--r-- 1 root root 19233 May 3 2018 install.php
|
|||
|
drwxr-xr-x 8 root root 4096 May 3 2018 lib
|
|||
|
-rw-r--r-- 1 root root 306 May 3 2018 README
|
|||
|
drwxr-xr-x 12 root root 4096 May 3 2018 vendor
|
|||
|
-rw-r--r-- 1 root root 21 May 3 2018 VERSION
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="cartographie-publique-mapcinayxyz">Cartographie (publique map.cinay.xyz)</h3>
|
|||
|
|
|||
|
<p><img src="/images/map.png" alt="Cartographie" width="100px" /></p>
|
|||
|
|
|||
|
<p><strong>Yunohost mode administration web</strong></p>
|
|||
|
|
|||
|
<p>créer le domaine <strong>map.cinay.xyz</strong> puis les certificats <strong>Let’s Encrypt</strong><br />
|
|||
|
Installation de l’application “Multi webapp for YunoHost” sur le domaine <strong>map.cinay.xyz</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/multi_webapp_ynh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>WARNING! Installing 3rd party applications may compromise the integrity and security of your system. You should probably NOT install it unless you know what you are doing. Are you willing to take that risk? [Y/N] : Y
|
|||
|
Available domains:
|
|||
|
- cinay.xyz
|
|||
|
- map.cinay.xyz
|
|||
|
- blog.cinay.xyz
|
|||
|
- liens.cinay.xyz
|
|||
|
- static.cinay.xyz
|
|||
|
Choose a domain for your Webapp (default: cinay.xyz): map.cinay.xyz
|
|||
|
Choose a path for your Webapp (default: /site): /
|
|||
|
Available users:
|
|||
|
- yannick
|
|||
|
Choose the YunoHost user: yannick
|
|||
|
Create a database? [yes | no] (default: no):
|
|||
|
Is it a public website ? [yes | no] (default: no): yes
|
|||
|
Info: [....................] > Retrieve arguments from the manifest
|
|||
|
Info: [#...................] > Check if the app can be installed
|
|||
|
Info: [##..................] > Store settings from manifest
|
|||
|
Info: [#####...............] > Setup SSOwat
|
|||
|
Info: [######..............] > Create final path
|
|||
|
Info: The directory /var/www/webapp_yannick already exist, do not recreate it.
|
|||
|
Info: [#######.............] > Create a dedicated user
|
|||
|
Info: [##########..........] > Configure php-fpm
|
|||
|
Warning: Reload the service php7.0-fpm
|
|||
|
Warning: Reload the service nginx
|
|||
|
Info: [###########.........] > Configure nginx
|
|||
|
Info: [############........] > Reload nginx
|
|||
|
Info: [####################] > Installation completed
|
|||
|
Success! The SSOwat configuration has been generated
|
|||
|
Success! Installation complete
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le dossier par défaut de “Multi webapp for YunoHost” <strong>/var/www/webapp_yannick/map.cinay.xyz_/</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm -r /var/www/webapp_yannick/map.cinay.xyz_/ # on supprime le dossier par défaut
|
|||
|
sudo ln -s /srv/osm-new /var/www/webapp_yannick/map.cinay.xyz_ # créer le lien
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Changer l’étiquette par “Cartes” en utilisant l’administration web “Applications”</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p><strong>Synchronisation locale des fichiers gpx</strong></p>
|
|||
|
|
|||
|
<p>Les fichiers gpx du dossier <strong>/srv/osm-new/file</strong> ne peuvent pas être utilisés par nextcloud et map pour une question de droits <br />
|
|||
|
Pour une utilisation par une application nextcloud dans le dossier <strong>/home/yannick/gpx</strong> on va le synchroniser avec le dossier <strong>/srv/osm-new/file/</strong> par lsyncd</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
apt install lsyncd # installation
|
|||
|
systemctl stop lsyncd # arrêt du service pour modifier la configuration
|
|||
|
mkdir /var/log/lsyncd
|
|||
|
touch /var/log/lsyncd/lsyncd.{log,status}
|
|||
|
# Configuration file goes on /etc/lsyncd:
|
|||
|
mkdir /etc/lsyncd
|
|||
|
# le fichier de configuration
|
|||
|
echo '
|
|||
|
settings = {
|
|||
|
logfile = "/var/log/lsyncd/lsyncd.log",
|
|||
|
statusFile = "/var/log/lsyncd/lsyncd.status"
|
|||
|
}
|
|||
|
|
|||
|
sync {
|
|||
|
default.rsync,
|
|||
|
source = "/srv/osm-new/file/",
|
|||
|
target = "/home/yannick/gpx",
|
|||
|
}
|
|||
|
' > /etc/lsyncd/lsyncd.conf.lua
|
|||
|
# lancement du service
|
|||
|
systemctl restart lsyncd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vue du fichier lsyncd.log</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Tue Dec 24 08:14:12 2019 Normal: recursive startup rsync: /srv/osm-new/file/ -> /home/yannick/gpx/
|
|||
|
Tue Dec 24 08:14:14 2019 Normal: Startup of "/srv/osm-new/file/" finished.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le contenu du dossier /home/yannick/gpx est synchronisé automatiquement avec le dossier /srv/osm-new/file/</p>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p><strong>IMPORTANT</strong> : Cette synchronisation est imposée pour l’utilisation d’une application nextcloud nommée <strong>gpxpod</strong></p>
|
|||
|
</blockquote>
|
|||
|
<font color="red">L'application <b>gpxpod</b> ne sait pas traiter les noms de fichiers avec des espaces</font>
|
|||
|
<p>, il faut exécuter dans le dossier <strong>/home/yannick/gpx</strong> , un bash <code class="language-plaintext highlighter-rouge">./remplacer-les-espaces-par_dans-les-noms-de-fichier.sh
|
|||
|
</code> en mode su</p>
|
|||
|
<font color="green"><b>LE PROBLEME EST RESOLU (DECEMBRE 2019)</b></font>
|
|||
|
|
|||
|
<p><img src="/images/map-web.png" alt="Cartographie" width="400px" /><br />
|
|||
|
<a href="https://map.cinay.xyz/">https://map.cinay.xyz/</a></p>
|
|||
|
|
|||
|
<h3 id="shaarli-publique-shaarlicinayxyz">Shaarli (publique shaarli.cinay.xyz)</h3>
|
|||
|
|
|||
|
<p><img src="/images/shaarli_logo.png" alt="image" width="50px" /><br />
|
|||
|
<em>Voulez-vous partager les liens que vous découvrez ? Shaarli est un gestionnaire de signets minimaliste et un service de partage de liens que vous pouvez installer sur votre propre serveur. Il est conçu pour être personnel (monoposte), rapide et pratique.</em></p>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Ajout domaine <strong>shaarli.cinay.xz</strong></li>
|
|||
|
<li>Certificats Let’s Encrypt pour le domaine</li>
|
|||
|
<li>Installer l’application <strong>shaarli</strong>
|
|||
|
<ul>
|
|||
|
<li>domaine : shaarli.cinay.xyz</li>
|
|||
|
<li>Chemin : /</li>
|
|||
|
<li>Site publique : Oui</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p><strong>ATTENTION!!!</strong> PROBLEMES+
|
|||
|
de droits et d’installation</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>En raison des problèmes évoqués, voici la procédure à suivre :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm -r /var/www/shaarli # suppression appli web shaarli installée par yunohost
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Réinstaller shaarli</strong><br />
|
|||
|
Télécharger la dernière version de Shaarli depuis la <a href="https://github.com/shaarli/Shaarli/releases">page des versions</a> (Télécharger l’archive <strong>shaarli-full</strong> pour inclure les dépendances).</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wget https://github.com/shaarli/Shaarli/releases/download/v0.11.1/shaarli-v0.11.1-full.tar.gz
|
|||
|
unzip shaarli-v0.11.1-full.tar.gz
|
|||
|
sudo mv Shaarli /var/www/shaarli
|
|||
|
sudo chown shaarli:shaarli -R /var/www/shaarli
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ouvrir le lien https://shaarli.cinay.xyz pour le paramétrage</p>
|
|||
|
|
|||
|
<p><img src="/images/shaarli01.png" alt="" width="500" /> <br />
|
|||
|
Après l’installation, se connecter en utilisateur/mot de passe</p>
|
|||
|
|
|||
|
<p><img src="/images/shaarli-web.png" alt="" width="400px" /><br />
|
|||
|
<a href="https://shaarli.cinay.xyz/">https://shaarli.cinay.xyz/</a></p>
|
|||
|
|
|||
|
<h3 id="wallabag-publique-lienscinayxyz">Wallabag (publique liens.cinay.xyz)</h3>
|
|||
|
|
|||
|
<p><em>wallabag est une application libre à héberger sur serveur permettant de sauvegarder des articles puis de les lire plus tard, sur n’importe quel appareil (navigateur, smartphone, tablette ou liseuse), que vous soyez connecté ou non.</em></p>
|
|||
|
|
|||
|
<p>Création domaine liens.cinay.xyz et certificats SSL<br />
|
|||
|
Installation de l’application “Wallabag for YunoHost” sur le domaine <strong>liens.cinay.xyz</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/wallabag2_ynh.git
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>WARNING! Installing 3rd party applications may compromise the integrity and security of your system. You should probably NOT install it unless you know what you are doing. Are you willing to take that risk? [Y/N] : Y
|
|||
|
Available domains:
|
|||
|
- cinay.xyz
|
|||
|
- map.cinay.xyz
|
|||
|
- blog.cinay.xyz
|
|||
|
- gitea.cinay.xyz
|
|||
|
- liens.cinay.xyz
|
|||
|
- static.cinay.xyz
|
|||
|
- calibre.cinay.xyz
|
|||
|
- shaarli.cinay.xyz
|
|||
|
Choose a domain for Wallabag (default: cinay.xyz): liens.cinay.xyz
|
|||
|
Choose a path for Wallabag (default: /wallabag): /
|
|||
|
Available users:
|
|||
|
- yannick
|
|||
|
Choose the Wallabag administrator: yannick
|
|||
|
Info: Installing application wallabag2…
|
|||
|
Info: [....................] > Validating installation parameters...
|
|||
|
Info: [++++................] > Installing dependencies...
|
|||
|
Info: [####................] > Creating a MySQL database...
|
|||
|
Info: [####++..............] > Setting up source files...
|
|||
|
Info: [######+.............] > Configuring nginx web server...
|
|||
|
Info: [#######.............] > Configuring system user...
|
|||
|
Info: [#######+............] > Configuring php-fpm...
|
|||
|
Info: [########+++++++++++.] > Configuring wallabag...
|
|||
|
Info: [###################.] > Configuring SSOwat...
|
|||
|
Info: [###################.] > Reloading nginx web server...
|
|||
|
Info: [####################] > Installation of wallabag2 completed
|
|||
|
Success! The SSOwat configuration has been generated
|
|||
|
Success! Installation complete
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="monitorix---privée-moncinayxyz">Monitorix - (privée mon.cinay.xyz)</h3>
|
|||
|
|
|||
|
<p><em>Monitorix est un outil de surveillance de système gratuit, open source et léger, conçu pour surveiller le plus grand nombre possible de services et de ressources du système. Il a été créé pour être utilisé sous des serveurs Linux/UNIX de production, mais en raison de sa simplicité et de sa petite taille, il peut également être utilisé sur des appareils embarqués.</em></p>
|
|||
|
|
|||
|
<p>Installer domaine et certificats</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain add mon.cinay.xyz
|
|||
|
yunohost domain cert-install mon.cinay.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer une application</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/monitorix_ynh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="sites-statiques-jekyll">Sites statiques (jekyll)</h2>
|
|||
|
|
|||
|
<h3 id="publique-staticcinayxyz">Publique static.cinay.xyz</h3>
|
|||
|
|
|||
|
<p><img src="/images/jekyll-300x133.png" alt="image" width="150px" /></p>
|
|||
|
|
|||
|
<p><strong>Création domaine static.cinay.xyz</strong><br />
|
|||
|
En mode administrateur ou en ligne de commande, créer un domaine static.cinay.xyz puis générer les certificats letsencrypt</p>
|
|||
|
|
|||
|
<p>En ligne de commande (passer en root)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain add static.cinay.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Administration password:
|
|||
|
Success! Successfully installed a self-signed certificate for domain static.cinay.xyz!
|
|||
|
Success! The configuration has been updated for service 'postfix'
|
|||
|
Success! The configuration has been updated for service 'nginx'
|
|||
|
Success! The configuration has been updated for service 'dnsmasq'
|
|||
|
Success! The configuration has been updated for service 'metronome'
|
|||
|
Success! The SSOwat configuration has been generated
|
|||
|
Success! The domain has been created
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain cert-install static.cinay.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Info: Now attempting install of certificate for domain static.cinay.xyz!
|
|||
|
Success! The SSOwat configuration has been generated
|
|||
|
Success! The configuration has been updated for service 'dnsmasq'
|
|||
|
Info: Parsing account key...
|
|||
|
Info: Parsing CSR...
|
|||
|
Info: Registering account...
|
|||
|
Info: Already registered!
|
|||
|
Info: Verifying static.cinay.xyz...
|
|||
|
Info: static.cinay.xyz verified!
|
|||
|
Info: Signing certificate...
|
|||
|
Info: Certificate signed!
|
|||
|
Success! Successfully installed Let's Encrypt certificate for domain static.cinay.xyz!
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="rbenv-gestion-des-versions-ruby">rbenv gestion des versions ruby</h3>
|
|||
|
|
|||
|
<p>Rbenv est un outil léger de gestion des versions de Ruby qui vous permet de changer facilement de version de Ruby.</p>
|
|||
|
|
|||
|
<p>Par défaut, Rbenv ne gère pas l’installation des versions de Ruby. ruby-build est un outil qui vous aide à installer n’importe quelle version de Ruby dont vous pourriez avoir besoin. Il est disponible en tant que programme autonome et en tant que plugin pour rbenv.</p>
|
|||
|
|
|||
|
<p>Installez les dépendances nécessaires à l’outil ruby-build pour construire Ruby à partir des sources :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt update
|
|||
|
sudo apt install git curl libssl-dev libreadline-dev zlib1g-dev autoconf bison build-essential libyaml-dev libreadline-dev libncurses5-dev libffi-dev libgdbm-dev
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ensuite, lancez la commande curl suivante pour installer les scripts rbenv et ruby-build :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl -sL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-installer | bash -
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si l’installation est réussie, le script imprimera quelque chose comme ceci :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Running doctor script to verify installation...
|
|||
|
Checking for `rbenv' in PATH: not found
|
|||
|
You seem to have rbenv installed in `/home/dbsuser/.rbenv/bin', but that
|
|||
|
directory is not present in PATH. Please add it to PATH by configuring
|
|||
|
your `~/.bashrc', `~/.zshrc', or `~/.config/fish/config.fish'.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Avant de commencer à utiliser rbenv, nous devons ajouter $HOME/.rbenv/bin à notre PATH.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
|
|||
|
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
|
|||
|
source ~/.bashrc
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les dernières versions stables</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rbenv install -l
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Maintenant que rbenv est installé sur notre système, nous pouvons facilement installer la dernière version stable de Ruby et la définir comme version par défaut avec :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rbenv install 2.7.1
|
|||
|
rbenv global 2.7.1
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifiez que Ruby a été correctement installé en imprimant le numéro de version :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ruby -v
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><code class="language-plaintext highlighter-rouge">ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]</code></p>
|
|||
|
|
|||
|
<h3 id="installer-jekyll-via-gem-et-bundler">Installer jekyll via gem et bundler</h3>
|
|||
|
|
|||
|
<p>On va utiliser gem pour installer Jekyll et Bundler qui est un outil utilisé pour gérer les dépendances de Gem.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>which bundler
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><code class="language-plaintext highlighter-rouge">/home/debadm/.rbenv/shims/bundler</code></p>
|
|||
|
|
|||
|
<p>Installer jekyl</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gem install jekyll # Patienter quelques minutes
|
|||
|
jekyll -v
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><code class="language-plaintext highlighter-rouge">jekyll 4.1.1</code></p>
|
|||
|
|
|||
|
<p>Cloner le dépôt staticyan</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://gitea.cinay.eu/yann/staticyan.git
|
|||
|
sudo mv staticyan /srv/
|
|||
|
sudo chown $USER.$USER -R /srv/staticyan
|
|||
|
cd /srv/staticyan/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier Gemfile</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>source 'https://rubygems.org'
|
|||
|
gem "jekyll", github: "jekyll/jekyll"
|
|||
|
|
|||
|
group :jekyll_plugins do
|
|||
|
gem "pygments.rb"
|
|||
|
gem "jekyll-paginate"
|
|||
|
gem 'jekyll-toc'
|
|||
|
gem 'jekyll-last-modified-at'
|
|||
|
gem 'rouge'
|
|||
|
end
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer jekyll via bundle</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bundle install
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les dossiers <em>images</em> <em>files</em> et <em>_posts</em> du site statique sont synchronisés par nextcloud dans /home/yannick/statique , il faut créer des liens avec jekyll</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tree -L 1 /home/yannick/statique/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/home/yannick/statique/
|
|||
|
├── files
|
|||
|
├── images
|
|||
|
└── _posts
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Création des liens</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm -rf /srv/staticyan/{files,images,_posts} # suppression des dossiers existants
|
|||
|
sudo ln -s /home/yannick/statique/_posts /srv/staticyan/_posts
|
|||
|
sudo ln -s /home/yannick/statique/images /srv/staticyan/images
|
|||
|
sudo ln -s /home/yannick/statique/files /srv/staticyan/files
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ce qui donne</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tree -L 1 /srv/staticyan/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/srv/staticyan/
|
|||
|
├── 404.html
|
|||
|
├── assets
|
|||
|
├── categories.html
|
|||
|
├── _config.yml
|
|||
|
├── feed.xml
|
|||
|
├── files -> /home/yannick/statique/files
|
|||
|
├── Gemfile
|
|||
|
├── Gemfile.lock
|
|||
|
├── images -> /home/yannick/statique/images
|
|||
|
├── _includes
|
|||
|
├── index.html
|
|||
|
├── _layouts
|
|||
|
├── _posts -> /home/yannick/statique/_posts
|
|||
|
├── README.md
|
|||
|
├── _site
|
|||
|
├── start.sh
|
|||
|
├── tags.html
|
|||
|
└── wikistatic.json
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Créer service staticyan</strong></p>
|
|||
|
|
|||
|
<p>Pour lancer le serveur <strong>staticyan</strong> au démarrage, utilisation d’un <u>service systemd</u><br />
|
|||
|
<strong>ATTENTION!</strong> , remplacer <em>User=utilisateur</em> par votre nom d’utilisateur <code class="language-plaintext highlighter-rouge">echo $USER</code><br />
|
|||
|
Relever le chemin complet de bundle : <code class="language-plaintext highlighter-rouge">which bundle</code></p>
|
|||
|
|
|||
|
<p>Création d’un service “staticyan” sous systemd</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/systemd/system/staticyan.service
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Contenu du fichier</p>
|
|||
|
|
|||
|
<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[Unit]</span>
|
|||
|
<span class="py">Description</span><span class="p">=</span><span class="s">service staticyan</span>
|
|||
|
<span class="py">After</span><span class="p">=</span><span class="s">network.target</span>
|
|||
|
|
|||
|
<span class="nn">[Service]</span>
|
|||
|
<span class="py">Type</span><span class="p">=</span><span class="s">simple</span>
|
|||
|
<span class="py">User</span><span class="p">=</span><span class="s">debadm</span>
|
|||
|
<span class="py">WorkingDirectory</span><span class="p">=</span><span class="s">/srv/staticyan</span>
|
|||
|
<span class="py">ExecStart</span><span class="p">=</span><span class="s">/home/debadm/.rbenv/shims/bundle exec jekyll build --watch</span>
|
|||
|
<span class="py">Restart</span><span class="p">=</span><span class="s">on-abort</span>
|
|||
|
|
|||
|
|
|||
|
<span class="nn">[Install]</span>
|
|||
|
<span class="py">WantedBy</span><span class="p">=</span><span class="s">multi-user.target</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Lancer le service <strong>staticyan</strong> :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl daemon-reload
|
|||
|
sudo systemctl start staticyan
|
|||
|
#Vérifier
|
|||
|
sudo systemctl status staticyan
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>● staticyan.service - jekyll Service
|
|||
|
Loaded: loaded (/etc/systemd/system/staticyan.service; disabled; vendor preset: enabled)
|
|||
|
Active: active (running) since Sun 2020-07-05 15:42:16 CEST; 16s ago
|
|||
|
Main PID: 31137 (bundle)
|
|||
|
Tasks: 1 (limit: 4915)
|
|||
|
CGroup: /system.slice/staticyan.service
|
|||
|
└─31137 /home/debadm/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/bin/jekyll build --watch
|
|||
|
|
|||
|
Jul 05 15:42:16 cinay.xyz systemd[1]: Started jekyll Service.
|
|||
|
Jul 05 15:42:18 cinay.xyz bundle[31137]: Configuration file: /srv/staticyan/_config.yml
|
|||
|
Jul 05 15:42:18 cinay.xyz bundle[31137]: Source: /srv/staticyan
|
|||
|
Jul 05 15:42:18 cinay.xyz bundle[31137]: Destination: /srv/staticyan/_site
|
|||
|
Jul 05 15:42:18 cinay.xyz bundle[31137]: Incremental build: disabled. Enable with --incremental
|
|||
|
Jul 05 15:42:18 cinay.xyz bundle[31137]: Generating...
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Valider le lancement du service staticyan au démarrage</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable staticyan
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>jekyll génére un dossier statique <strong>/srv/staticyan/_site</strong></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>Installation de l’application “Multi webapp for YunoHost” sur le domaine <strong>static.cinay.xyz</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/multi_webapp_ynh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>WARNING! Installing 3rd party applications may compromise the integrity and security of your system. You should probably NOT install it unless you know what you are doing. Are you willing to take that risk? [Y/N] : Y
|
|||
|
Available domains:
|
|||
|
- cinay.xyz
|
|||
|
- map.cinay.xyz
|
|||
|
- blog.cinay.xyz
|
|||
|
- liens.cinay.xyz
|
|||
|
- static.cinay.xyz
|
|||
|
Choose a domain for your Webapp (default: cinay.xyz): static.cinay.xyz
|
|||
|
Choose a path for your Webapp (default: /site): /
|
|||
|
Available users:
|
|||
|
- yannick
|
|||
|
Choose the YunoHost user: yannick
|
|||
|
Create a database? [yes | no] (default: no):
|
|||
|
Is it a public website ? [yes | no] (default: no): yes
|
|||
|
Info: [....................] > Retrieve arguments from the manifest
|
|||
|
Info: [#...................] > Check if the app can be installed
|
|||
|
Info: [##..................] > Store settings from manifest
|
|||
|
Info: [#####...............] > Setup SSOwat
|
|||
|
Info: [######..............] > Create final path
|
|||
|
Info: The directory /var/www/webapp_yannick already exist, do not recreate it.
|
|||
|
Info: [#######.............] > Create a dedicated user
|
|||
|
Warning: Reload the service php7.0-fpm
|
|||
|
Info: [##########..........] > Configure php-fpm
|
|||
|
Info: [###########.........] > Configure nginx
|
|||
|
Warning: Reload the service nginx
|
|||
|
Info: [############........] > Reload nginx
|
|||
|
Info: [####################] > Installation completed
|
|||
|
Success! The SSOwat configuration has been generated
|
|||
|
Success! Installation complete
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le dossier par défaut de “Multi webapp for YunoHost” <strong>/var/www/webapp_yannick/static.cinay.xyz_/</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm -r /var/www/webapp_yannick/static.cinay.xyz_/ # on supprime le dossier par défaut
|
|||
|
sudo ln -s /srv/staticyan/_site /var/www/webapp_yannick/static.cinay.xyz_ # créer le lien
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Changer l’étiquette par “Static” en utilisant l’administration web “Applications”</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p><img src="/images/static-web.png" alt="static-web" width="400px" /><br />
|
|||
|
Le site statique sur le lien <a href="https://static.xoyize.xyz">https://static.xoyize.xyz</a></p>
|
|||
|
|
|||
|
<h4 id="menu-sur-les-posts-jekyll-toc">Menu sur les “posts” (jekyll-toc)</h4>
|
|||
|
|
|||
|
<p>Installer jekyll-toc : <code class="language-plaintext highlighter-rouge">gem install jekyll-toc</code> <br />
|
|||
|
Ajouter <code class="language-plaintext highlighter-rouge">jekyll-toc</code> à la rubrique <em>plugins</em> du fichier <strong>_config.yml</strong><br />
|
|||
|
Modifier le fichier _includes/posts.html : <code class="language-plaintext highlighter-rouge">content</code> → <code class="language-plaintext highlighter-rouge">content | toc </code></p>
|
|||
|
|
|||
|
<p>Le temps de génération du site est multiplié par 6 (on passe de 5 à 30 secondes ???)<br />
|
|||
|
La solution est de passer en mode incrémental (seul le fichier modifié est regénéré)</p>
|
|||
|
|
|||
|
<p>Modifier le service <code class="language-plaintext highlighter-rouge">sudo nano /etc/systemd/system/staticyan.service</code> : <br />
|
|||
|
Remplacer <code class="language-plaintext highlighter-rouge">ExecStart=/home/debadm/.rbenv/shims/bundle exec jekyll build --watch</code> <br />
|
|||
|
Par <code class="language-plaintext highlighter-rouge">ExecStart=/home/debadm/.rbenv/shims/bundle exec jekyll build --watch --incremental</code><br />
|
|||
|
Recharger <code class="language-plaintext highlighter-rouge">sudo systemctl daemon-reload</code> et relancer <code class="language-plaintext highlighter-rouge">sudo systemctl start staticyan</code></p>
|
|||
|
|
|||
|
<h3 id="privée-blogcinayxyz-facultatif">Privée blog.cinay.xyz (FACULTATIF)</h3>
|
|||
|
|
|||
|
<p>Essais → <a href="https://blog.cinay.xyz/2019/12/Blog-statique-jekyll-Yunohost-cinay.xyz.html">Blog statique de type jekyll sur site cinay.xyz</a></p>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Site statique de type jekyll identique dans la conception à static.cinay.xyz</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>Yunohost administrateur</p>
|
|||
|
|
|||
|
<ol>
|
|||
|
<li>Ajout domaine <strong>blog.cinay.xz</strong></li>
|
|||
|
<li>Certificats Let’s Encrypt pour le domaine</li>
|
|||
|
<li>Installer l’application <strong>Multi webapp for YunoHost</strong>
|
|||
|
<ul>
|
|||
|
<li>domaine : blog.cinay.xyz</li>
|
|||
|
<li>Chemin : /</li>
|
|||
|
<li>Site publique : Non</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
|
|||
|
<p><img src="/images/blog-web.png" alt="" width="400px" /><br />
|
|||
|
Accès site blog/test <a href="https://blog.cinay.xyz">https://blog.cinay.xyz</a></p>
|
|||
|
|
|||
|
<p>Le dossier par défaut de “Multi webapp for YunoHost” <strong>/var/www/webapp_yannick/blog.cinay.xyz_/</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm -r /var/www/webapp_yannick/blog.cinay.xyz_/ # on supprime le dossier par défaut
|
|||
|
sudo ln -s /srv/basicblog/_site /var/www/webapp_yannick/blog.cinay.xyz_ # créer le lien
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>MODIFICATION , ajout exclusion dossier <strong>_posts/archives</strong> dans le fichier de configuration <strong>_config.yml</strong></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p><strong>Modifications sur static et blog</strong></p>
|
|||
|
|
|||
|
<p>Le but recherché est un accès publique sur le site static.cinay.xyz et privé sur le site blog.cinay.xyz.</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><strong>static.cinay.xyz</strong> accède au dossier pour les billets <strong>publiques</strong></li>
|
|||
|
<li><strong>blog.cinay.xyz</strong> accède au dossier pour les billets <strong>publiques et privés</strong></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Arrêt des services</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl stop jekyll
|
|||
|
sudo systemctl stop basicblog
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>static.cinay.xyz</strong></p>
|
|||
|
|
|||
|
<p>Exclusions dans <strong>static.cinay.xyz</strong> (fichier de configuration <strong>/srv/wikistatic/_config.yml</strong>)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>exclude:
|
|||
|
|
|||
|
- .jekyll-cache
|
|||
|
- _posts/archives/
|
|||
|
- _posts/private/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les liens</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ls -l /srv/wikistatic/ |grep ^l
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lrwxrwxrwx 1 debadm debadm 28 Apr 12 10:25 files -> /home/yannick/statique/files
|
|||
|
lrwxrwxrwx 1 debadm debadm 29 Apr 12 10:26 images -> /home/yannick/statique/images
|
|||
|
lrwxrwxrwx 1 debadm debadm 29 Apr 12 10:27 _posts -> /home/yannick/statique/_posts
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>blog.cinay.xyz</strong></p>
|
|||
|
|
|||
|
<p>Exclusions dans <strong>blog.cinay.xyz</strong> (fichier de configuration <strong>/srv/basicblog/_config.yml</strong>)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>exclude:
|
|||
|
|
|||
|
- .jekyll-cache
|
|||
|
- _posts/archives/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier le lien _posts</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ls -l /srv/basicblog/ |grep ^l
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lrwxrwxrwx 1 debadm debadm 28 Dec 25 12:18 files -> /home/yannick/statique/files
|
|||
|
lrwxrwxrwx 1 debadm debadm 29 Dec 25 12:18 images -> /home/yannick/statique/images
|
|||
|
lrwxrwxrwx 1 debadm debadm 37 Apr 12 10:22 _posts -> /home/yannick/statique/_posts
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>basicblog</strong><br />
|
|||
|
Ajout affichage de la lettre P sur fond rouge , si le billet contient le tag <code class="language-plaintext highlighter-rouge">private: true</code></p>
|
|||
|
|
|||
|
<p><strong>Redémarrer les services</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl start jekyll
|
|||
|
sudo systemctl start basicblog
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="sauvegarde-yunohost">Sauvegarde yunohost</h2>
|
|||
|
|
|||
|
<p>Création d’une sauvegarde complète yunohost</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
yunohost backup create -n Backup-Yunohost-cinay.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Sauvegarde automatique tous les jours</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
crontab -e
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Sauvegarde yunohost
|
|||
|
15 01 * * * /bin/rm /home/yunohost.backup/archives/* && /usr/bin/yunohost backup create -n Backup-Yunohost-cinay.xyz > /dev/null
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="sauvegarde-borgbackup">Sauvegarde BorgBackup</h2>
|
|||
|
|
|||
|
<p><img src="/images/borg-logo.png" alt="" /></p>
|
|||
|
|
|||
|
<h3 id="serveur-client-cinayxyz">serveur client cinay.xyz</h3>
|
|||
|
|
|||
|
<h4 id="connexion-ssh">connexion SSH</h4>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Pour une connexion via ssh vous devez ajouter la clé publique <em>cinay_ed25519</em> du <strong>serveur client cinay.xyz</strong> au fichier <em>~/.ssh/authorized_keys</em> du <strong>serveur backup xoyaz.xyz</strong></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>Procédure</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh usernl@5.2.79.107 -p 55036 -i /home/yannick/.ssh/OVZ-STORAGE-128 # connexion SSH serveur backup
|
|||
|
sudo -s # passer en super utilisateur
|
|||
|
cat >> /srv/data/borg-backups/.ssh/authorized_keys
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Copier/coller le contenu du fichier du fichier de clef publique (fichier /root/.ssh/cinay_ed25519.pub de la machine à sauvegarder <strong>cinay.xyz</strong> ) dans ce terminal, et presser [Ctrl]+[D] pour valider.</p>
|
|||
|
|
|||
|
<p>Test depuis le serveur client (c’est lui qui possède la clé privée)</p>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p><strong>AU PREMIER passage une question est posée , saisir oui ou yes</strong></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
ssh -p 55036 -i /root/.ssh/cinay_ed25519 borg@xoyaz.xyz
|
|||
|
The authenticity of host '[xoyaz.xyz]:55036 ([2a04:52c0:101:7ae::7a5e]:55036)' can't be established.
|
|||
|
ECDSA key fingerprint is SHA256:PDXQBhTh4oj0cSzgnjCun+J60JDUEk7VeLH2YHZbwMc.
|
|||
|
Are you sure you want to continue connecting (yes/no)? yes
|
|||
|
Warning: Permanently added '[xoyaz.xyz]:55036,[2a04:52c0:101:7ae::7a5e]:55036' (ECDSA) to the list of known hosts.
|
|||
|
Linux backup 2.6.32-042stab134.3 #1 SMP Sun Oct 14 12:26:01 MSK 2018 x86_64
|
|||
|
_ _
|
|||
|
| |__ __ _ __ | |__ _ _ _ __
|
|||
|
| '_ \/ _` |/ _|| / /| || || '_ \
|
|||
|
|_.__/\__,_|\__||_\_\ \_,_|| .__/
|
|||
|
|_|
|
|||
|
$ pwd
|
|||
|
/srv/data/borg-backups
|
|||
|
$
|
|||
|
# saisir exit pour sortir
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h4 id="création-du-dépôt-distant-cinayxyz-a-faire-une-seule-fois">Création du dépôt distant cinay.xyz (A FAIRE UNE SEULE FOIS)</h4>
|
|||
|
|
|||
|
<p>Dans la terminologie borg, l’emplacement où les sauvegardes sont stockées est appelé le référentiel borg (dépôt).</p>
|
|||
|
|
|||
|
<p>sudo -s</p>
|
|||
|
|
|||
|
<p>Créer un fichier avec la passphrase <code class="language-plaintext highlighter-rouge">nano /root/.borg/passphrase</code> et copier le résultat de la commande <code class="language-plaintext highlighter-rouge">< /dev/urandom tr -dc A-Za-z0-9 | head -c${1:-64};echo;</code> dans le fichier</p>
|
|||
|
|
|||
|
<p>Initialisation dépôt</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>export BORG_PASSPHRASE="`cat /root/.borg/passphrase`"
|
|||
|
export BORG_RSH='ssh -i /root/.ssh/cinay_ed25519'
|
|||
|
borg init --encryption=repokey-blake2 ssh://borg@xoyaz.xyz:55036/srv/data/borg-backups/cinay.xyz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Remote: Borg 1.0.9: exception <span class="k">in </span>RPC call:
|
|||
|
Remote: Traceback <span class="o">(</span>most recent call last<span class="o">)</span>:
|
|||
|
Remote: File <span class="s2">"/usr/lib/python3/dist-packages/borg/remote.py"</span>, line 108, <span class="k">in </span>serve
|
|||
|
Remote: raise InvalidRPCMethod<span class="o">(</span>method<span class="o">)</span>
|
|||
|
Remote: borg.remote.InvalidRPCMethod: get_free_nonce
|
|||
|
Remote: Platform: Linux backup 2.6.32-042stab134.3 <span class="c">#1 SMP Sun Oct 14 12:26:01 MSK 2018 x86_64</span>
|
|||
|
Remote: Linux: debian 9.9
|
|||
|
Remote: Borg: 1.0.9 Python: CPython 3.5.3
|
|||
|
Remote: PID: 18282 CWD: /srv/data/borg-backups
|
|||
|
Remote: sys.argv: <span class="o">[</span><span class="s1">'/usr/bin/borg'</span>, <span class="s1">'serve'</span>, <span class="s1">'--umask=077'</span><span class="o">]</span>
|
|||
|
Remote: SSH_ORIGINAL_COMMAND: None
|
|||
|
Remote:
|
|||
|
Please upgrade to borg version 1.1+ on the server <span class="k">for </span>safer AES-CTR nonce handling.
|
|||
|
|
|||
|
By default repositories initialized with this version will produce security
|
|||
|
errors <span class="k">if </span>written to with an older version <span class="o">(</span>up to and including Borg 1.0.8<span class="o">)</span><span class="nb">.</span>
|
|||
|
|
|||
|
If you want to use these older versions, you can disable the check by running:
|
|||
|
borg upgrade <span class="nt">--disable-tam</span> ssh://borg@xoyaz.xyz:55036/srv/data/borg-backups/cinay.xyz
|
|||
|
|
|||
|
See https://borgbackup.readthedocs.io/en/stable/changes.html#pre-1-0-9-manifest-spoofing-vulnerability <span class="k">for </span>details about the security implications.
|
|||
|
|
|||
|
IMPORTANT: you will need both KEY AND PASSPHRASE to access this repo!
|
|||
|
Use <span class="s2">"borg key export"</span> to <span class="nb">export </span>the key, optionally <span class="k">in </span>printable format.
|
|||
|
Write down the passphrase. Store both at safe place<span class="o">(</span>s<span class="o">)</span><span class="nb">.</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h4 id="sauvegarde-cinayxyz--xoyazxyz">Sauvegarde cinay.xyz → xoyaz.xyz</h4>
|
|||
|
|
|||
|
<p>Le fichier des exclusions</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /root/.borg/exclusions
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/dev
|
|||
|
/proc
|
|||
|
/sys
|
|||
|
/tmp
|
|||
|
/run
|
|||
|
/mnt
|
|||
|
/media
|
|||
|
lost+found
|
|||
|
/home/yunohost.*
|
|||
|
/opt
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer un bash</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
nano /root/.borg/borg-backup
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/sh
|
|||
|
#
|
|||
|
# Script de sauvegarde.
|
|||
|
#
|
|||
|
# Envoie les sauvegardes sur un serveur distant, via le programme Borg.
|
|||
|
# Les sauvegardes sont chiffrées
|
|||
|
#
|
|||
|
|
|||
|
set -e
|
|||
|
|
|||
|
BACKUP_DATE=`date +%Y-%m-%d-%Hh%M`
|
|||
|
LOG_PATH=/var/log/borg-backup.log
|
|||
|
|
|||
|
export BORG_PASSPHRASE="`cat ~root/.borg/passphrase`"
|
|||
|
export BORG_RSH='ssh -i /root/.ssh/cinay_ed25519'
|
|||
|
BORG_REPOSITORY=ssh://borg@xoyaz.xyz:55036/srv/data/borg-backups/cinay.xyz
|
|||
|
BORG_ARCHIVE=${BORG_REPOSITORY}::${BACKUP_DATE}
|
|||
|
|
|||
|
borg create \
|
|||
|
-v --progress --stats --compression lzma,9 \
|
|||
|
--exclude-caches \
|
|||
|
$BORG_ARCHIVE \
|
|||
|
/home/yunohost.backup \
|
|||
|
>> ${LOG_PATH} 2>&1
|
|||
|
|
|||
|
# Nettoyage des anciens backups
|
|||
|
# On conserve
|
|||
|
# - une archive par jour les 7 derniers jours,
|
|||
|
# - une archive par semaine pour les 4 dernières semaines,
|
|||
|
# - une archive par mois pour les 6 derniers mois.
|
|||
|
|
|||
|
borg prune \
|
|||
|
-v --list --stats --keep-daily=7 --keep-weekly=4 --keep-monthly=6 \
|
|||
|
$BORG_REPOSITORY \
|
|||
|
>> ${LOG_PATH} 2>&1
|
|||
|
|
|||
|
exit
|
|||
|
|
|||
|
# ancienne sauvegarde
|
|||
|
borg create \
|
|||
|
-v --stats --compression lzma,9 \
|
|||
|
--exclude-from /root/.borg/exclusions.xoyaz.xyz --exclude-caches \
|
|||
|
$BORG_ARCHIVE \
|
|||
|
/ \
|
|||
|
>> ${LOG_PATH} 2>&1
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le rendre exécutable</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod +x /root/.borg/borg-backup-xoyaz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>On ajoute la sauvegarde des bases mariaDB sous forme SQL</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /root/.borg/dumpmysql.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#!/bin/bash
|
|||
|
|
|||
|
# Configuration de base: datestamp e.g. YYYYMMDD
|
|||
|
DATE=$(date +"%Y%m%d")
|
|||
|
|
|||
|
# Dossier où sauvegarder les backups (créez le d'abord!)
|
|||
|
BACKUP_DIR="/srv/backup/mysql"
|
|||
|
|
|||
|
# Identifiants MySQL
|
|||
|
MYSQL_USER="root"
|
|||
|
MYSQL_PASSWORD=$(cat /etc/yunohost/mysql )
|
|||
|
GZIP="$(which gzip)"
|
|||
|
|
|||
|
# Commandes MySQL (aucune raison de modifier ceci)
|
|||
|
MYSQL="$(which mysql)"
|
|||
|
MYSQLDUMP="$(which mysqldump)"
|
|||
|
|
|||
|
# Bases de données MySQL à ignorer
|
|||
|
SKIPDATABASES="Database|information_schema|performance_schema|mysql"
|
|||
|
|
|||
|
# Nombre de jours à garder les dossiers (seront effacés après X jours)
|
|||
|
RETENTION=14
|
|||
|
|
|||
|
# ---- NE RIEN MODIFIER SOUS CETTE LIGNE ------------------------------------------
|
|||
|
#
|
|||
|
# Create a new directory into backup directory location for this date
|
|||
|
mkdir -p $BACKUP_DIR/$DATE
|
|||
|
|
|||
|
# Retrieve a list of all databases
|
|||
|
databases=`$MYSQL -u$MYSQL_USER -p$MYSQL_PASSWORD -e "SHOW DATABASES;" | grep -Ev "($SKIPDATABASES)"`
|
|||
|
|
|||
|
# Dump the databases in seperate names and gzip the .sql file
|
|||
|
for db in $databases; do
|
|||
|
echo $db
|
|||
|
$MYSQLDUMP --force --opt --user=$MYSQL_USER -p$MYSQL_PASSWORD --skip-lock-tables --events --databases $db | $GZIP > "$BACKUP_DIR/$DATE/$db.sql.gz"
|
|||
|
done
|
|||
|
|
|||
|
# Remove files older than X days
|
|||
|
|
|||
|
find $BACKUP_DIR/* -mtime +$RETENTION -delete
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le rendre exécutable</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod +x /root/.borg/dumpmysql.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Programmer les tâches</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>crontab -e # ajouter les ligne suivantes en fin de fichier
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Sauvegarde sur serveur de backup distant xoyaz.xyz avec BorgBackup
|
|||
|
30 01 * * * /root/.borg/dumpmysql.sh > /dev/null
|
|||
|
00 02 * * * /root/.borg/borg-backup-xoyaz > /dev/null
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="ajout-dune-clé-diffie-hellman-et-vérification-par-ssllabs">Ajout d’une clé Diffie-Hellman et vérification par SSLlabs</h2>
|
|||
|
|
|||
|
<h3 id="ajout-dune-clé-diffie-hellman">Ajout d’une clé Diffie-Hellman</h3>
|
|||
|
|
|||
|
<p><em>L’algorithme Diffie-Hellman est un algorithme d’échange de clés, utilisé notamment lors de l’ouverture d’une connexion à un site sécurisé via le protocole SSL/TLS.</em></p>
|
|||
|
|
|||
|
<p>Exécuter les instructions suivantes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># passer en mode su
|
|||
|
sudo -s
|
|||
|
# Générer une clé Diffie Hellman (patienter quelques minutes)
|
|||
|
openssl dhparam -out /etc/ssl/private/dh2048.pem -outform PEM -2 2048
|
|||
|
# Enlever commentaire en début de ligne sur tous les fichiers de configuration nginx
|
|||
|
find /etc/nginx/conf.d/ -name "*.conf" -exec sed -i 's/#ssl_dhparam/ssl_dhparam/g' {} \;
|
|||
|
# Redémarrer nginx
|
|||
|
systemctl restart nginx
|
|||
|
# sortie su
|
|||
|
exit
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="vérification-par-ssllabs">Vérification par ssllabs</h3>
|
|||
|
|
|||
|
<p>Ouvrir le lien <a href="https://www.ssllabs.com/ssltest/analyze.html?d=cinay.xyz">https://www.ssllabs.com/ssltest/analyze.html?d=cinay.xyz</a> sur un navigateur et patienter…</p>
|
|||
|
|
|||
|
<p><img src="/images/ssllabs-cinay.xyz.png" alt="ssllabs" width="600" /></p>
|
|||
|
|
|||
|
<h2 id="go-node">Go Node</h2>
|
|||
|
|
|||
|
<h3 id="go">Go</h3>
|
|||
|
|
|||
|
<p><img src="/images/golang-color-icon2.png" alt="golang" width="50" /></p>
|
|||
|
|
|||
|
<p>Go installation (Debian) , installer la dernière version de Go (https://golang.org/dl/)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ~
|
|||
|
wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz
|
|||
|
sudo tar -C /usr/local -xzf go1.14.2.linux-amd64.tar.gz
|
|||
|
rm go1.14.2.linux-amd64.tar.gz
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Environnement de configuration</p>
|
|||
|
|
|||
|
<p>Bash: <strong>~/.bashrc</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p $HOME/go
|
|||
|
echo "export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin" >> ~/.bashrc
|
|||
|
echo "export GOPATH=$HOME/go" >> ~/.bashrc
|
|||
|
source ~/.bashrc
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="nodejs">Nodejs</h3>
|
|||
|
|
|||
|
<p><img src="/images/Node_logo.png" alt="nodejs" width="50" /></p>
|
|||
|
|
|||
|
<p>Installer la version LTS de nodejs pour le frontend.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt-get install curl software-properties-common -y
|
|||
|
curl -sL https://deb.nodesource.com/setup_12.x | sudo bash -
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>## Run `sudo apt-get install -y nodejs` to install Node.js 12.x and npm
|
|||
|
## You may also need development tools to build native addons:
|
|||
|
sudo apt-get install gcc g++ make
|
|||
|
## To install the Yarn package manager, run:
|
|||
|
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
|||
|
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
|
|||
|
sudo apt-get update && sudo apt-get install yarn
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Nodejs</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt-get install -y nodejs
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="serveur-audio-gonic-ziccinayxyz">Serveur Audio Gonic (zic.cinay.xyz)</h2>
|
|||
|
|
|||
|
<p><img src="/images/gonic002.png" alt="Texte alternatif" width="200" /><br />
|
|||
|
<em><a href="https://github.com/sentriz/gonic">Gonic</a> écrit en go est une alternative à Subsonic.org, accessible par un proxy nginx<br />
|
|||
|
La seule application qui accepte de fonctionner avec répertoires montés par FUSE.</em></p>
|
|||
|
|
|||
|
<h3 id="caractéristiques">Caractéristiques</h3>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>la navigation par dossier (en gardant votre arborescence complète intacte)</li>
|
|||
|
<li>la navigation par balises (à l’aide de <a href="https://taglib.org/">taglib</a> - supporte mp3, opus, flac, ape, m4a, wav, etc.)</li>
|
|||
|
<li>transcodage et mise en cache audio à la volée (nécessite <a href="https://ffmpeg.org/">ffmpeg</a>) (merci spijet)</li>
|
|||
|
<li>balayage assez rapide (avec ma bibliothèque de ~27k pistes, le balayage initial prend environ 10m, et environ 5s après de manière incrémentielle)</li>
|
|||
|
<li>plusieurs utilisateurs, chacun ayant ses propres préférences de transcodage, ses listes de lecture, ses meilleures pistes, ses meilleurs artistes, etc.</li>
|
|||
|
<li><a href="https://www.last.fm/">last.fm</a> scrobbling</li>
|
|||
|
<li>similarités entre les artistes et biographies de la dernière api.fm</li>
|
|||
|
<li>une interface web pour la configuration (configurer last.fm, gérer les utilisateurs, lancer des analyses, etc.)</li>
|
|||
|
<li>un support pour le tag album-artist, pour ne pas encombrer votre liste d’artistes avec des apparitions d’albums de compilation</li>
|
|||
|
<li>écrit en go, donc léger et adapté à un pi framboise, etc.</li>
|
|||
|
<li>plus récent sel et token auth</li>
|
|||
|
<li>testé sur <a href="https://f-droid.org/en/packages/github.daneren2005.dsub/">dsub</a>, <a href="http://jamstash.com/">jamstash</a>, <a href="https://gitlab.com/sumner/sublime-music/">musique sublime</a> et<a href="https://apps.apple.com/us/app/soundwaves/id736139596"> ondes sonores</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="sshfs-fstab">SSHFS fstab</h3>
|
|||
|
|
|||
|
<p>Le dossier “musique” est distant (serveur xoyaz.xyz)<br />
|
|||
|
Il faut créer une liaison réseau sécurisée entre <strong>cinay.xyz ← → xoyaz.xyz</strong><br />
|
|||
|
On va utiliser SSHFS (<em>Secure shell file system (ou SSHFS) permet le partage d’un système de fichiers de manière sécurisée en utilisant le protocole SFTP de SSH</em>)</p>
|
|||
|
|
|||
|
<p>Créer un dossier “backup” local</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mkdir -p /opt/backup
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installation</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install sshfs
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Autorisations</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Autorisations “utilisateur”
|
|||
|
<ul>
|
|||
|
<li>Exécuter <code class="language-plaintext highlighter-rouge">sshfs</code> (ou toute autre commande de montage FUSE) avec l’option <code class="language-plaintext highlighter-rouge">-o allow_other</code></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li>Autoriser l’accès “root” des supports <strong>fuse</strong>
|
|||
|
<ul>
|
|||
|
<li>Ajouter <code class="language-plaintext highlighter-rouge">user_allow_other</code> au fichier <strong>/etc/fuse.conf</strong></li>
|
|||
|
<li>Exécuter <code class="language-plaintext highlighter-rouge">sshfs</code> (ou toute autre commande de montage FUSE) avec l’option <code class="language-plaintext highlighter-rouge">-o allow_root</code></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Clé privée <strong>OVZ-STORAGE-128</strong> pour accéder au serveur xoyaz.xyz</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod 600 //home/debadm/.ssh/OVZ-STORAGE-128
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Exécution manuelle</strong> pour authentifier la clé avec utilisateur “debian”</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
sshfs -o allow_other usernl@5.2.79.107:/home/usernl/backup /opt/backup -C -p 55036 -oIdentityFile=//home/debadm/.ssh/OVZ-STORAGE-128
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The authenticity of host '[5.2.79.107]:55036 ([5.2.79.107]:55036)' can't be established.
|
|||
|
ECDSA key fingerprint is SHA256:PDXQBhTh4oj0cSzgnjCun+J60JDUEk7VeLH2YHZbwMc.
|
|||
|
Are you sure you want to continue connecting (yes/no)? yes
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>NOTE: Il est préférable de mettre l’adresse IP du serveur ,les domaines peuvent ne pas être “résolus”</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>Après vérification , <code class="language-plaintext highlighter-rouge">ls ~/music</code> , déconnexion <code class="language-plaintext highlighter-rouge">sudo fusermount -u /opt/gonic/music</code></p>
|
|||
|
|
|||
|
<p><strong>Montage fstab</strong></p>
|
|||
|
|
|||
|
<p>ajouter la ligne suivante au fichier <strong>/etc/fstab</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>usernl@5.2.79.107:/home/usernl/backup /opt/backup fuse.sshfs _netdev,identityfile=//home/debadm/.ssh/OVZ-STORAGE-128,allow_other,port=55036 0 0
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Montage pour authentifier la clé avec utilisateur “root”</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mount -a
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérification</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ls /opt/backup/musique/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p><strong>ATTENTION!!! NE PAS OUBLIER D’EXCLURE <code class="language-plaintext highlighter-rouge">/opt/backup</code> DE TOUTE SAUVEGARDE (/root/.borg/exclusions.xoyaz.xyz)</strong></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3 id="installation-gonic">Installation gonic</h3>
|
|||
|
|
|||
|
<p>dans le répertoire utilisateur <strong>$HOME</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># les dépendances
|
|||
|
sudo apt install build-essential git sqlite libtag1-dev ffmpeg libasound2-dev pkg-config # for debian like
|
|||
|
cd $HOME/
|
|||
|
# cloner
|
|||
|
git clone https://gitea.cinay.eu/yann/golang-subsonic.git
|
|||
|
cd golang-subsonic/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Construire l’exécutable “gonic” et le copier dans /usr/local/bin</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./_do_build_server
|
|||
|
sudo cp gonic /usr/local/bin/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="créer-le-service-gonic">Créer le service gonic</h3>
|
|||
|
|
|||
|
<p>Que fait le service ?</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Le dossier fuse “music” et monté au démarrage par fstab</li>
|
|||
|
<li>lancer le serveur “gonic” en écoute local sur le port 4747 avec les options <code class="language-plaintext highlighter-rouge">-music-path</code>, <code class="language-plaintext highlighter-rouge">-db-path</code> et <code class="language-plaintext highlighter-rouge">-proxy-prefix</code></li>
|
|||
|
<li>A l’arrêt,tuer la tâche “gonic”</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Tester le serveur</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/usr/local/bin/gonic -music-path /opt/backup/musique -db-path /opt/gonic/gonic.db -proxy-prefix /
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2020/05/19 17:56:37 starting gonic v0.8.8
|
|||
|
2020/05/19 17:56:37 provided config
|
|||
|
2020/05/19 17:56:37 cache-path /tmp/gonic_cache
|
|||
|
2020/05/19 17:56:37 config-path
|
|||
|
2020/05/19 17:56:37 db-path /opt/gonic/gonic.db
|
|||
|
2020/05/19 17:56:37 jukebox-enabled false
|
|||
|
2020/05/19 17:56:37 listen-addr 0.0.0.0:4747
|
|||
|
2020/05/19 17:56:37 music-path /opt/gonic/music
|
|||
|
2020/05/19 17:56:37 proxy-prefix /
|
|||
|
2020/05/19 17:56:37 scan-interval 0
|
|||
|
2020/05/19 17:56:37 version false
|
|||
|
2020/05/19 17:56:37 migration (1/7) '202002192100' finished
|
|||
|
2020/05/19 17:56:37 migration (2/7) '202002192019' finished
|
|||
|
2020/05/19 17:56:37 migration (3/7) '202002192222' finished
|
|||
|
2020/05/19 17:56:37 migration (4/7) '202003111222' finished
|
|||
|
2020/05/19 17:56:37 migration (5/7) '202003121330' finished
|
|||
|
2020/05/19 17:56:37 migration (6/7) '202003241509' finished
|
|||
|
2020/05/19 17:56:37 migration (7/7) '202004302006' finished
|
|||
|
2020/05/19 17:56:37 starting job 'http'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Arrêt par Ctrl+C</p>
|
|||
|
|
|||
|
<p>Chaque service généré par systemd est configuré par un fichier .service qui se trouve dans le répertoire <strong>/etc/systemd/system</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/systemd/system/gonic.service
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Unit]
|
|||
|
Description=Gonic audio server
|
|||
|
After=network.target
|
|||
|
|
|||
|
[Service]
|
|||
|
Type=simple
|
|||
|
|
|||
|
Restart=on-failure
|
|||
|
RestartSec=10
|
|||
|
|
|||
|
ExecStart=/usr/local/bin/gonic -music-path /opt/backup/musique -db-path /opt/gonic/gonic.db -proxy-prefix /
|
|||
|
|
|||
|
[Install]
|
|||
|
WantedBy=multi-user.target
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Recharger <code class="language-plaintext highlighter-rouge">systemd</code> puis démarrer le service:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl daemon-reload
|
|||
|
sudo systemctl start gonic.service
|
|||
|
sudo systemctl status gonic.service
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>● gonic.service - Gonic audio server
|
|||
|
Loaded: loaded (/etc/systemd/system/gonic.service; enabled; vendor preset: enabled)
|
|||
|
Active: active (running) since Mon 2020-07-06 12:23:53 CEST; 13s ago
|
|||
|
Main PID: 6431 (gonic)
|
|||
|
Tasks: 6 (limit: 4915)
|
|||
|
CGroup: /system.slice/gonic.service
|
|||
|
└─6431 /usr/local/bin/gonic -music-path /opt/backup/musique -db-path /opt/gonic/gonic.db -proxy-prefix
|
|||
|
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 cache-path /tmp/gonic_cache
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 config-path
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 db-path /opt/gonic/gonic.db
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 jukebox-enabled false
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 listen-addr 0.0.0.0:4747
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 music-path /opt/backup/musique
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 proxy-prefix /
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 scan-interval 0
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 version false
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 starting job 'http'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Visualiser le journal</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo journalctl -t gonic
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 starting gonic v0.8.8
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 provided config
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 cache-path /tmp/gonic_cache
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 config-path
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 db-path /opt/gonic/gonic.db
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 jukebox-enabled false
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 listen-addr 0.0.0.0:4747
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 music-path /opt/backup/musique
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 proxy-prefix /
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 scan-interval 0
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 version false
|
|||
|
Jul 06 12:23:53 cinay.xyz gonic[6431]: 2020/07/06 12:23:53 starting job 'http'
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Si tout est en ordre , on active le service</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable gonic.service
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="ziccinayxyz">zic.cinay.xyz</h3>
|
|||
|
|
|||
|
<p>En mode su<br />
|
|||
|
Créer le domaine zic.cinay.xyz : <code class="language-plaintext highlighter-rouge">yunohost domain add zic.cinay.xyz</code><br />
|
|||
|
Les certificats : <code class="language-plaintext highlighter-rouge">yunohost domain cert-install zic.cinay.xyz</code></p>
|
|||
|
|
|||
|
<p>Installer l’application Multi web app sur le domaine zic.cinay.xyz (accès publique)</p>
|
|||
|
|
|||
|
<h3 id="proxy-nginx">proxy nginx</h3>
|
|||
|
|
|||
|
<p><em>Gonic est un serveur local http sur le port 4747 et pour un accès externe il nous faut un proxy</em></p>
|
|||
|
|
|||
|
<p><strong>Proxy nginx</strong> - configuration <strong>/etc/nginx/conf.d/zic.cinay.xyz.d/webapp_zic.cinay.xyz_.conf</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#sub_path_only rewrite ^/$ / permanent;
|
|||
|
location / {
|
|||
|
# Proxy zic server
|
|||
|
|
|||
|
proxy_set_header Host $host;
|
|||
|
proxy_set_header X-Real-IP $remote_addr;
|
|||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|||
|
|
|||
|
proxy_pass http://localhost:4747;
|
|||
|
proxy_read_timeout 120;
|
|||
|
|
|||
|
# Include SSOWAT user panel.
|
|||
|
include conf.d/yunohost_panel.conf.inc;
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>On vérifie et on relance le serveur nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nginx -t
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>En cas d’avertissement , modifier <strong>/etc/nginx/nginx.conf</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nginx -t
|
|||
|
nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size
|
|||
|
nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size
|
|||
|
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
|
|||
|
nginx: configuration file /etc/nginx/nginx.conf test is successful
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajouter au fichier <strong>/etc/nginx/nginx.conf</strong> , après <code class="language-plaintext highlighter-rouge">htpp {</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> proxy_headers_hash_max_size 512;
|
|||
|
proxy_headers_hash_bucket_size 128;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Rechargement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl reload nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Accès <a href="https://zic.cinay.xyz">https://zic.cinay.xyz</a></p>
|
|||
|
|
|||
|
<p><img src="/images/gonic003.png" alt="gonic" width="400" /></p>
|
|||
|
|
|||
|
<h2 id="diagramsnet">Diagrams.net</h2>
|
|||
|
|
|||
|
<p><em>Application en ligne qui permet de faire des schémas et du dessin vectoriel.</em></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/diagramsnet_ynh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Choose a domain name for Diagrams.net (default: cinay.xyz):
|
|||
|
Choose a path for Diagrams.net (default: /diagram):
|
|||
|
Is it a public application? [yes | no] (default: no):
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="libreqr">LibreQR</h2>
|
|||
|
|
|||
|
<p><em>Un générateur de codes QR</em></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://code.antopie.org/miraty/qr_ynh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Choose a domain for LibreQR (default: cinay.xyz):
|
|||
|
Choose a path for LibreQR (default: /qr):
|
|||
|
Is it a public application? [yes | no] (default: yes):
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="maintenance-yunohost">Maintenance yunohost</h2>
|
|||
|
|
|||
|
<h3 id="ajout-domaine-cinayeu-messagerie--obsolete">Ajout domaine cinay.eu (messagerie) -OBSOLETE</h3>
|
|||
|
|
|||
|
<p>Ajout domaine <strong>cinay.eu</strong> et utilisateur <strong>yann</strong><br />
|
|||
|
Modification de la DNS OVH du domaine cinay.eu (<strong>NE CONCERNE QUE LA PARTIE MESSAGERIE</strong>)<br />
|
|||
|
Les champs modifiés:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>IN MX 10 cinay.xyz.
|
|||
|
IN TXT "v=spf1 a mx ip4:51.75.120.106 ip6:2001:41d0:305:2100::4dc0 -all"
|
|||
|
IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDTvvyg816px/VJY6XoyfyPpC8wtrziMU1IunI4AuMdP/WxnGr2HPR26ORn/n16PnNuyGdzC/AUG2917d2VJ88/oLQO8ZCePk4lcWFAqRyfPvyUc+nbnE8XhYbJ9udYzQ8zxsm/7LEfgFoOXKRi9DC7rgyf7F1sRUycS8MS6kIQxQIDAQAB"
|
|||
|
IN TXT "v=DMARC1; p=none"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="nextcloud-1">Nextcloud</h3>
|
|||
|
|
|||
|
<p>Une mise à jour récente a déclenché un “upgrade” <strong>nextcloud</strong> de la version 15 à 18 <br />
|
|||
|
Pour info la version 15 utilise php7.0 qui est installé par défaut<br />
|
|||
|
La version 18 utilise PHP7.3</p>
|
|||
|
|
|||
|
<p>La mise à jour n’a pas posé de problème <br />
|
|||
|
Par contre , des anomalies sont affichés lors de la consultation (en admin) des <em>avertissements de sécutité</em></p>
|
|||
|
|
|||
|
<p><strong>Anomalies</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Il est important pour la sécurité et la performance de votre instance que celle-ci soit correctement configurée. Afin de vous aider, votre instance Nextcloud effectue des vérifications automatiques. Pour de plus amples informations, veuillez consulter la documentation liée.
|
|||
|
Il y a quelques avertissements concernant votre configuration.
|
|||
|
|
|||
|
MySQL est utilisée comme base de données mais ne supporte pas les caractères codés sur 4 octets. Pour pouvoir manipuler les caractères sur 4 octets (comme les émoticônes) sans problème dans les noms de fichiers ou les commentaires par exemple, il est recommandé d'activer le support 4 octets dans MySQL. Pour plus de détails, lisez la [page de documentation à ce sujet](https://docs.nextcloud.com/server/18/go.php?to=admin-mysql-utf8mb4)
|
|||
|
|
|||
|
La base de données a quelques index manquant. L'ajout d'index dans de grandes tables peut prendre un certain temps. Elles ne sont donc pas ajoutées automatiquement. En exécutant "occ db:add-missing-indices", ces index manquants pourront être ajoutés manuellement pendant que l'instance continue de tourner. Une fois les index ajoutés, les requêtes sur ces tables sont généralement beaucoup plus rapides.
|
|||
|
Index "twofactor_providers_uid" manquant dans la table "oc_twofactor_providers".
|
|||
|
Index "version" manquant dans la table "oc_whats_new".
|
|||
|
Index "cards_abid" manquant dans la table "oc_cards".
|
|||
|
Index "cards_prop_abid" manquant dans la table "oc_cards_properties".
|
|||
|
Index "calendarobject_calid_index" manquant dans la table "oc_calendarobjects_props".
|
|||
|
Index "schedulobj_principuri_index" manquant dans la table "oc_schedulingobjects".
|
|||
|
|
|||
|
Merci de consulter les [guides d'installation ↗](https://docs.nextcloud.com/server/18/go.php?to=admin-install) et de vérifier les erreurs ou avertissements des logs.
|
|||
|
|
|||
|
Vérifier la sécurité de votre Nextcloud grâce à notre [scan de sécurité ↗](https://scan.nextcloud.com/)
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Corrections MariaDb/nextcloud</strong></p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><a href="https://docs.nextcloud.com/server/18/go.php?to=admin-mysql-utf8mb4">Enabling MySQL 4-byte support</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Ouvrir 2 terminaux sur le site <br />
|
|||
|
Respecter l’ordre des opérations</p>
|
|||
|
|
|||
|
<p><strong>→ PREMIER TERMINAL</strong></p>
|
|||
|
|
|||
|
<p>mysql -uroot -p$(cat /etc/yunohost/mysql )</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Welcome to the MariaDB monitor. Commands end with ; or \g.
|
|||
|
Your MariaDB connection id is 76
|
|||
|
Server version: 10.1.44-MariaDB-0+deb9u1 Debian 9.11
|
|||
|
|
|||
|
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
|
|||
|
|
|||
|
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
|
|||
|
|
|||
|
MariaDB [(none)]> show variables like 'innodb_file_format';
|
|||
|
+--------------------+----------+
|
|||
|
| Variable_name | Value |
|
|||
|
+--------------------+----------+
|
|||
|
| innodb_file_format | Antelope |
|
|||
|
+--------------------+----------+
|
|||
|
1 row in set (0.01 sec)
|
|||
|
|
|||
|
MariaDB [nextcloud]> SET GLOBAL innodb_file_format=Barracuda;
|
|||
|
Query OK, 0 rows affected (0.00 sec)
|
|||
|
|
|||
|
MariaDB [nextcloud]> show variables like 'innodb_file_per_table';
|
|||
|
+-----------------------+-------+
|
|||
|
| Variable_name | Value |
|
|||
|
+-----------------------+-------+
|
|||
|
| innodb_file_per_table | ON |
|
|||
|
+-----------------------+-------+
|
|||
|
1 row in set (0.00 sec)
|
|||
|
|
|||
|
MariaDB [(none)]> quit
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>→ SECOND TERMINAL</strong></p>
|
|||
|
|
|||
|
<p>ATTENTION /usr/bin/php7.3 est utilisé pour nextcloud</p>
|
|||
|
|
|||
|
<p>On passe en mode maintenance</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /var/www/nextcloud
|
|||
|
sudo -u nextcloud /usr/bin/php7.3 occ maintenance:mode --on
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Maintenance mode enabled</p>
|
|||
|
|
|||
|
<p>Redémarrer mysql suite aux manipulations effectuées dans le premier terminal</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart mysqld
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>→ PREMIER TERMINAL</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mysql -uroot -p$(cat /etc/yunohost/mysql )
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MariaDB [(none)]> ALTER DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
|||
|
Query OK, 1 row affected (0.00 sec)
|
|||
|
|
|||
|
MariaDB [(none)]> quit
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour éviter l’ERREUR</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>An exception occurred while executing ‘ALTER TABLE [TABLE_NAME] CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;’:
|
|||
|
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mysql -uroot -p$(cat /etc/yunohost/mysql ) nextcloud
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MariaDB [nextcloud]> set global innodb_large_prefix=on;
|
|||
|
Query OK, 0 rows affected (0.00 sec)
|
|||
|
|
|||
|
MariaDB [nextcloud]> set global innodb_file_format=Barracuda;
|
|||
|
Query OK, 0 rows affected (0.00 sec)
|
|||
|
|
|||
|
MariaDB [nextcloud]> quit
|
|||
|
Bye
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>→ SECOND TERMINAL</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u nextcloud /usr/bin/php7.3 occ config:system:set mysql.utf8mb4 --type boolean --value="true"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Nextcloud is in maintenance mode - no apps have been loaded
|
|||
|
|
|||
|
System config value mysql.utf8mb4 set to boolean true
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u nextcloud /usr/bin/php7.3 occ maintenance:repair # patienter
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>désactiver la maintenance</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -u nextcloud /usr/bin/php7.3 occ maintenance:mode --off
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Maintenance mode disabled</p>
|
|||
|
|
|||
|
<p><strong>Correction tâche cron</strong></p>
|
|||
|
|
|||
|
<p>La tâche cron n’est jamais exécuté (normalement tous les 5 minutes) car elle n’existe pas</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Avertissements de sécurité & configuration
|
|||
|
|
|||
|
Il est important pour la sécurité et la performance de votre instance que celle-ci soit correctement configurée. Afin de vous aider, votre instance Nextcloud effectue des vérifications automatiques. Pour de plus amples informations, veuillez consulter la documentation liée.
|
|||
|
Il y a quelques erreurs concernant votre configuration.
|
|||
|
|
|||
|
Dernière tâche de fond a fonctionné il y a Il y a 1 heure. Quelque chose s'est mal passé. Vérifier les paramètres des tâches de fond
|
|||
|
|
|||
|
Merci de consulter les guides d'installation ↗ et de vérifier les erreurs ou avertissements des logs.
|
|||
|
|
|||
|
Vérifier la sécurité de votre Nextcloud grâce à notre scan de sécurité ↗
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer la tâche dans un “scheduleur” cron</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
|
|||
|
crontab -u nextcloud -e
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajouter</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>*/5 * * * * /usr/bin/php7.3 -f /var/www/nextcloud/cron.php > /dev/null 2>&1
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier sur le site nextcloud</p>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud-cinay.xyz.png" alt="" /></p>
|
|||
|
|
|||
|
<h3 id="passage-public--private">Passage public → private</h3>
|
|||
|
|
|||
|
<p>En mode su</p>
|
|||
|
|
|||
|
<p>Rechercher l’application concernée dans la liste des applications installées</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app list -i
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
|
|||
|
6:
|
|||
|
description: Empty App without FTP access
|
|||
|
id: multi_webapp__5
|
|||
|
installed: True
|
|||
|
label: basicblog site statique
|
|||
|
license: GPL-3.0
|
|||
|
name: Multi custom webapp
|
|||
|
|
|||
|
...
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Basculer le flag <code class="language-plaintext highlighter-rouge">is_public: '1'</code> → <code class="language-plaintext highlighter-rouge">is_public: '0'</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sed -i "s/is_public: '1'/is_public: '0'/g" /etc/yunohost/apps/multi_webapp__5/settings.yml
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Supprimer la ligne avec le flag <code class="language-plaintext highlighter-rouge">skipped_uris: /</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sed -i "/^skipped_uris/d" /etc/yunohost/apps/multi_webapp__5/settings.yml
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p><strong>Note: **Pour passer de **private → public</strong> , flag <code class="language-plaintext highlighter-rouge">is_public: '1'</code> et ajout d’une ligne <code class="language-plaintext highlighter-rouge">skipped_uris: /</code> en avant dernière ligne du fichier <strong>/etc/yunohost/apps/multi_webapp__5/settings.yml</strong></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>Régénérer le fichier de configuratio</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app ssowatconf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="désactiver-overlay-en-bas-écran">Désactiver overlay en bas écran</h3>
|
|||
|
|
|||
|
<p><strong>overlay en bas écran</strong><br />
|
|||
|
Ouvrir le fichier <strong>/usr/share/ssowat/portal/assets/js/ynh_portal.js</strong> et commenter la zone suivante</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/*
|
|||
|
// Inject portal button
|
|||
|
var portalButton = document.createElement('a');
|
|||
|
portalButton.setAttribute('id', 'ynh-overlay-switch');
|
|||
|
portalButton.setAttribute('href', '/yunohost/sso/');
|
|||
|
portalButton.setAttribute('class', 'disableAjax');
|
|||
|
document.body.insertBefore(portalButton, null);
|
|||
|
// Make portal button draggable, for user convenience
|
|||
|
make_element_draggable('ynh-overlay-switch');
|
|||
|
*/
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Regénérer la configuration</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo yunohost app ssowatconf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>sur les applications web multi…</strong></p>
|
|||
|
|
|||
|
<p>Il faut éditer la configuration nginx qui se trouve dans <strong>/etc/nginx/conf.d/domaine.tld.d/webapp_domaine.tld_.conf</strong> et enlever cette ligne</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Include SSOWAT user panel.
|
|||
|
include conf.d/yunohost_panel.conf.inc;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>A noter que de façon alternative, il est techniquement possible de remplacer le script qui charge le logo par un autre script (par exemple pour afficher un menu, ou quelques chose de plus discret, sur l’ensemble des apps.</p>
|
|||
|
|
|||
|
<p>les fichiers concernés</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/nginx/conf.d/static.cinay.xyz.d/webapp_static.cinay.xyz_.conf
|
|||
|
/etc/nginx/conf.d/blog.cinay.xyz.d/webapp_blog.cinay.xyz_.conf
|
|||
|
/etc/nginx/conf.d/map.cinay.xyz.d/webapp_map.cinay.xyz_.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Redémarrer nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl restart nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="désinstaller-monitorix">Désinstaller monitorix</h3>
|
|||
|
|
|||
|
<p>Liste des applications installées</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo yunohost app list -i
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apps:
|
|||
|
...
|
|||
|
4:
|
|||
|
description: A monitoring tools
|
|||
|
id: monitorix
|
|||
|
installed: True
|
|||
|
label: Monitorix
|
|||
|
license: GPL-2.0
|
|||
|
name: Monitorix
|
|||
|
...
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo yunohost app remove monitorix
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="27042020---désactiver-basicblog">27/04/2020 - Désactiver basicblog</h3>
|
|||
|
|
|||
|
<p>Il n’existe plus qu’un seul site statique : static.cinay.xyz<br />
|
|||
|
Dossier : /srv/wikistatic<br />
|
|||
|
Les liens<br />
|
|||
|
files -> /home/yannick/statique/files<br />
|
|||
|
images -> /home/yannick/statique/images<br />
|
|||
|
_posts -> /home/yannick/statique/_posts</p>
|
|||
|
|
|||
|
<p>Désactivation basicblog<br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo systemctl stop basicblog</code><br />
|
|||
|
<code class="language-plaintext highlighter-rouge">sudo systemctl disable basicblog</code><br />
|
|||
|
Suppression dossier : <code class="language-plaintext highlighter-rouge">sudo rm -r /srv/basicblog</code><br />
|
|||
|
Désinstaller blog.cinay.xyz :<code class="language-plaintext highlighter-rouge">sudo yunohost app remove multi_webapp__5</code><br />
|
|||
|
Supprimer le service : <code class="language-plaintext highlighter-rouge">sudo rm /etc/systemd/system/basicblog.service && sudo systemctl daemon-reload</code></p>
|
|||
|
|
|||
|
<p>3 sous-domaines non utilisés : blog liens et mon</p>
|
|||
|
|
|||
|
<h3 id="13-juillet-2020---sauvegardes-et-synchronisations">13 juillet 2020 - Sauvegardes et synchronisations</h3>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Suppression sauvegarde via <strong>borg</strong></li>
|
|||
|
<li>On n’envoie pas systématiquement la sauvegarde yunohost</li>
|
|||
|
<li>Ajout sauvegarde complète via <strong>rsync</strong> avec exclusions</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Le fichier du schéduleur <strong>crontab</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Synchroniser le dossier "CalibreTechnique" entre le serveur de backup distant xoyaz.xyz et le serveur local cinay.xyz
|
|||
|
15 01 * * * /usr/bin/rsync -avz -e "ssh -p 55036 -i .ssh/OVZ-STORAGE-128 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress usernl@xoyaz.xyz:/home/usernl/backup/CalibreTechnique/* /home/yunohost.multimedia/share/eBook/
|
|||
|
# Sauvegarde des bases mysql
|
|||
|
00 01 * * * /root/.borg/dumpmysql.sh > /dev/null
|
|||
|
|
|||
|
# Sauvegarde complète via rsync
|
|||
|
00 02 * * * cd /;/usr/bin/rsync -aAXv -e "ssh -p 55036 -i /home/debadm/.ssh/OVZ-STORAGE-128 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --delete --progress --exclude={dev/*,proc/*,sys/*,tmp/*,run/*,mnt/*,media/*,opt/*,lost+found} / usernl@xoyaz.xyz:/home/usernl/backup/rsync-cinay.xyz/
|
|||
|
|
|||
|
# Sauvegarde yunohost
|
|||
|
## 15 01 * * * /bin/rm /home/yunohost.backup/archives/* && /usr/bin/yunohost backup create -n Backup-Yunohost-cinay.xyz > /dev/null
|
|||
|
# Sauvegarde sur distant avec BorgBackup
|
|||
|
## 00 02 * * * /root/.borg/borg-backup > /dev/null
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="20-juillet-2020">20 juillet 2020</h3>
|
|||
|
|
|||
|
<p>Supprimer</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><strong>Calibre</strong> : <code class="language-plaintext highlighter-rouge">yunohost app remove calibreweb</code> <code class="language-plaintext highlighter-rouge">yunohost domain remove calibre.cinay.xyz</code></li>
|
|||
|
<li><strong>Diagrams</strong> : <code class="language-plaintext highlighter-rouge">yunohost app remove diagramsnet</code></li>
|
|||
|
<li><strong>LibreQR</strong> : <code class="language-plaintext highlighter-rouge">yunohost app remove qr</code></li>
|
|||
|
<li><strong>shaarli</strong> : <code class="language-plaintext highlighter-rouge">yunohost app remove shaarli</code> <code class="language-plaintext highlighter-rouge">yunohost domain remove shaarli.cinay.xyz</code></li>
|
|||
|
<li><strong>multi_webapp__2</strong> <code class="language-plaintext highlighter-rouge">yunohost app remove multi_webapp__2</code> <code class="language-plaintext highlighter-rouge">yunohost domain remove map.cinay.xyz</code></li>
|
|||
|
<li><strong>transmission</strong> : <code class="language-plaintext highlighter-rouge">yunohost app remove transmission</code></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="nginx-warning">Nginx warning</h3>
|
|||
|
|
|||
|
<p>En cas d’avertissement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nginx -t
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size
|
|||
|
nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size
|
|||
|
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
|
|||
|
nginx: configuration file /etc/nginx/nginx.conf test is successful
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ajouter au fichier <strong>/etc/nginx/nginx.conf</strong> , après <code class="language-plaintext highlighter-rouge">htpp {</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> proxy_headers_hash_max_size 512;
|
|||
|
proxy_headers_hash_bucket_size 128;
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Rechargement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl reload nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2018-12-21T00:00:00+01:00"><!-- start custom article footer snippet -->
|
|||
|
|
|||
|
<!-- end custom article footer snippet -->
|
|||
|
<!--
|
|||
|
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
|
|||
|
|
|||
|
 </div>
|
|||
|
-->
|
|||
|
</footer>
|
|||
|
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2018/11/28/RaspberryPI-Raspbian-FlashDriveUSB3-RealTimeClock-EcranTactile2p8SPI.html">Raspbian Raspberry PI 3 + USB 3.0 Flash Drive FIT 32GB + "Real Time Clock" + écran tactile TFT LCD 2.8"</a></div><div class="next"><span>SUIVANT</span><a href="/2018/12/29/Archlinux-Son-Hdmi-Casque-en-un-clic.html">XFCE, changer de sortie Audio ,HDMI ou Analogique (casque), en un clic</a></div></div></div>
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
<script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
$(function() {
|
|||
|
var $this ,$scroll;
|
|||
|
var $articleContent = $('.js-article-content');
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
|
|||
|
$scroll = $(scroll);
|
|||
|
|
|||
|
$articleContent.find('.highlight').each(function() {
|
|||
|
$this = $(this);
|
|||
|
$this.attr('data-lang', $this.find('code').attr('data-lang'));
|
|||
|
});
|
|||
|
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
|
|||
|
$this = $(this);
|
|||
|
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
|
|||
|
});
|
|||
|
$articleContent.on('click', '.anchor', function() {
|
|||
|
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
})();
|
|||
|
</script>
|
|||
|
|
|||
|
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
|
|||
|
<!-- end custom main bottom snippet -->
|
|||
|
</div>
|
|||
|
</div></div></div></div>
|
|||
|
</div><script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $body = $('body'), $window = $(window);
|
|||
|
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
|
|||
|
var activeCount = 0;
|
|||
|
function modal(options) {
|
|||
|
var $root = this, visible, onChange, hideWhenWindowScroll = false;
|
|||
|
var scrollTop;
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
visible = _options.initialVisible === undefined ? false : show;
|
|||
|
onChange = _options.onChange;
|
|||
|
hideWhenWindowScroll = _options.hideWhenWindowScroll;
|
|||
|
}
|
|||
|
function init() {
|
|||
|
setState(visible);
|
|||
|
}
|
|||
|
function setState(isShow) {
|
|||
|
if (isShow === visible) {
|
|||
|
return;
|
|||
|
}
|
|||
|
visible = isShow;
|
|||
|
if (visible) {
|
|||
|
activeCount++;
|
|||
|
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
|
|||
|
$root.addClass('modal--show');
|
|||
|
$pageMain.scrollTop(scrollTop);
|
|||
|
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
|
|||
|
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
|
|||
|
$window.on('keyup', handleKeyup);
|
|||
|
} else {
|
|||
|
activeCount > 0 && activeCount--;
|
|||
|
$root.removeClass('modal--show');
|
|||
|
$window.scrollTop(scrollTop);
|
|||
|
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
|
|||
|
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
|
|||
|
$window.off('keyup', handleKeyup);
|
|||
|
}
|
|||
|
onChange && onChange(visible);
|
|||
|
}
|
|||
|
function show() {
|
|||
|
setState(true);
|
|||
|
}
|
|||
|
function hide() {
|
|||
|
setState(false);
|
|||
|
}
|
|||
|
function handleKeyup(e) {
|
|||
|
// Char Code: 27 ESC
|
|||
|
if (e.which === 27) {
|
|||
|
hide();
|
|||
|
}
|
|||
|
}
|
|||
|
setOptions(options);
|
|||
|
init();
|
|||
|
return {
|
|||
|
show: show,
|
|||
|
hide: hide,
|
|||
|
$el: $root
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.modal = modal;
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
|
|||
|
(function () {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
// search panel
|
|||
|
var search = (window.search || (window.search = {}));
|
|||
|
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
|
|||
|
true : window.useDefaultSearchBox ;
|
|||
|
|
|||
|
var $searchModal = $('.js-page-search-modal');
|
|||
|
var $searchToggle = $('.js-search-toggle');
|
|||
|
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
|
|||
|
var modalVisible = false;
|
|||
|
search.searchModal = searchModal;
|
|||
|
|
|||
|
var $searchBox = null;
|
|||
|
var $searchInput = null;
|
|||
|
var $searchClear = null;
|
|||
|
|
|||
|
function getModalVisible() {
|
|||
|
return modalVisible;
|
|||
|
}
|
|||
|
search.getModalVisible = getModalVisible;
|
|||
|
|
|||
|
function handleModalChange(visible) {
|
|||
|
modalVisible = visible;
|
|||
|
if (visible) {
|
|||
|
search.onShow && search.onShow();
|
|||
|
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
|
|||
|
} else {
|
|||
|
search.onShow && search.onHide();
|
|||
|
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
|
|||
|
setTimeout(function() {
|
|||
|
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
|
|||
|
search.clear && search.clear();
|
|||
|
window.pageAsideAffix && window.pageAsideAffix.refresh();
|
|||
|
}, 400);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
$searchToggle.on('click', function() {
|
|||
|
modalVisible ? searchModal.hide() : searchModal.show();
|
|||
|
});
|
|||
|
// Char Code: 83 S, 191 /
|
|||
|
$(window).on('keyup', function(e) {
|
|||
|
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
|
|||
|
modalVisible || searchModal.show();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
if (useDefaultSearchBox) {
|
|||
|
$searchBox = $('.js-search-box');
|
|||
|
$searchInput = $searchBox.children('input');
|
|||
|
$searchClear = $searchBox.children('.js-icon-clear');
|
|||
|
search.getSearchInput = function() {
|
|||
|
return $searchInput.get(0);
|
|||
|
};
|
|||
|
search.getVal = function() {
|
|||
|
return $searchInput.val();
|
|||
|
};
|
|||
|
search.setVal = function(val) {
|
|||
|
$searchInput.val(val);
|
|||
|
};
|
|||
|
|
|||
|
$searchInput.on('focus', function() {
|
|||
|
$(this).addClass('focus');
|
|||
|
});
|
|||
|
$searchInput.on('blur', function() {
|
|||
|
$(this).removeClass('focus');
|
|||
|
});
|
|||
|
$searchInput.on('input', window.throttle(function() {
|
|||
|
var val = $(this).val();
|
|||
|
if (val === '' || typeof val !== 'string') {
|
|||
|
search.clear && search.clear();
|
|||
|
} else {
|
|||
|
$searchBox.addClass('not-empty');
|
|||
|
search.onInputNotEmpty && search.onInputNotEmpty(val);
|
|||
|
}
|
|||
|
}, 400));
|
|||
|
$searchClear.on('click', function() {
|
|||
|
$searchInput.val(''); $searchBox.removeClass('not-empty');
|
|||
|
search.clear && search.clear();
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><div class="search search--dark">
|
|||
|
<div class="main">
|
|||
|
<div class="search__header">Recherche</div>
|
|||
|
<div class="search-bar">
|
|||
|
<div class="search-box js-search-box">
|
|||
|
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
|
|||
|
<input id="search-input" type="text" />
|
|||
|
<div class="search-box__icon-clear js-icon-clear">
|
|||
|
<a><i class="fas fa-times"></i></a>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
|
|||
|
Annuler</button>
|
|||
|
</div>
|
|||
|
<div id="results-container" class="search-result js-search-result"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<!-- Script pointing to search-script.js -->
|
|||
|
<script>/*!
|
|||
|
* Simple-Jekyll-Search
|
|||
|
* Copyright 2015-2020, Christian Fei
|
|||
|
* Licensed under the MIT License.
|
|||
|
*/
|
|||
|
|
|||
|
(function(){
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Templater_7 = {
|
|||
|
compile: compile,
|
|||
|
setOptions: setOptions
|
|||
|
}
|
|||
|
|
|||
|
const options = {}
|
|||
|
options.pattern = /\{(.*?)\}/g
|
|||
|
options.template = ''
|
|||
|
options.middleware = function () {}
|
|||
|
|
|||
|
function setOptions (_options) {
|
|||
|
options.pattern = _options.pattern || options.pattern
|
|||
|
options.template = _options.template || options.template
|
|||
|
if (typeof _options.middleware === 'function') {
|
|||
|
options.middleware = _options.middleware
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function compile (data) {
|
|||
|
return options.template.replace(options.pattern, function (match, prop) {
|
|||
|
const value = options.middleware(prop, data[prop], options.template)
|
|||
|
if (typeof value !== 'undefined') {
|
|||
|
return value
|
|||
|
}
|
|||
|
return data[prop] || match
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
'use strict';
|
|||
|
|
|||
|
function fuzzysearch (needle, haystack) {
|
|||
|
var tlen = haystack.length;
|
|||
|
var qlen = needle.length;
|
|||
|
if (qlen > tlen) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
if (qlen === tlen) {
|
|||
|
return needle === haystack;
|
|||
|
}
|
|||
|
outer: for (var i = 0, j = 0; i < qlen; i++) {
|
|||
|
var nch = needle.charCodeAt(i);
|
|||
|
while (j < tlen) {
|
|||
|
if (haystack.charCodeAt(j++) === nch) {
|
|||
|
continue outer;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
var _$fuzzysearch_1 = fuzzysearch;
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
|
|||
|
|
|||
|
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
|
|||
|
|
|||
|
function FuzzySearchStrategy () {
|
|||
|
this.matches = function (string, crit) {
|
|||
|
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
|
|||
|
|
|||
|
function LiteralSearchStrategy () {
|
|||
|
this.matches = function (str, crit) {
|
|||
|
if (!str) return false
|
|||
|
|
|||
|
str = str.trim().toLowerCase()
|
|||
|
crit = crit.trim().toLowerCase()
|
|||
|
|
|||
|
return crit.split(' ').filter(function (word) {
|
|||
|
return str.indexOf(word) >= 0
|
|||
|
}).length === crit.split(' ').length
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$Repository_4 = {
|
|||
|
put: put,
|
|||
|
clear: clear,
|
|||
|
search: search,
|
|||
|
setOptions: __setOptions_4
|
|||
|
}
|
|||
|
|
|||
|
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
|
|||
|
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
|
|||
|
|
|||
|
function NoSort () {
|
|||
|
return 0
|
|||
|
}
|
|||
|
|
|||
|
const data = []
|
|||
|
let opt = {}
|
|||
|
|
|||
|
opt.fuzzy = false
|
|||
|
opt.limit = 10
|
|||
|
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = NoSort
|
|||
|
opt.exclude = []
|
|||
|
|
|||
|
function put (data) {
|
|||
|
if (isObject(data)) {
|
|||
|
return addObject(data)
|
|||
|
}
|
|||
|
if (isArray(data)) {
|
|||
|
return addArray(data)
|
|||
|
}
|
|||
|
return undefined
|
|||
|
}
|
|||
|
function clear () {
|
|||
|
data.length = 0
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function isObject (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
|
|||
|
}
|
|||
|
|
|||
|
function isArray (obj) {
|
|||
|
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
|
|||
|
}
|
|||
|
|
|||
|
function addObject (_data) {
|
|||
|
data.push(_data)
|
|||
|
return data
|
|||
|
}
|
|||
|
|
|||
|
function addArray (_data) {
|
|||
|
const added = []
|
|||
|
clear()
|
|||
|
for (let i = 0, len = _data.length; i < len; i++) {
|
|||
|
if (isObject(_data[i])) {
|
|||
|
added.push(addObject(_data[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
return added
|
|||
|
}
|
|||
|
|
|||
|
function search (crit) {
|
|||
|
if (!crit) {
|
|||
|
return []
|
|||
|
}
|
|||
|
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
|
|||
|
}
|
|||
|
|
|||
|
function __setOptions_4 (_opt) {
|
|||
|
opt = _opt || {}
|
|||
|
|
|||
|
opt.fuzzy = _opt.fuzzy || false
|
|||
|
opt.limit = _opt.limit || 10
|
|||
|
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
|
|||
|
opt.sort = _opt.sort || NoSort
|
|||
|
opt.exclude = _opt.exclude || []
|
|||
|
}
|
|||
|
|
|||
|
function findMatches (data, crit, strategy, opt) {
|
|||
|
const matches = []
|
|||
|
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
|
|||
|
const match = findMatchesInObject(data[i], crit, strategy, opt)
|
|||
|
if (match) {
|
|||
|
matches.push(match)
|
|||
|
}
|
|||
|
}
|
|||
|
return matches
|
|||
|
}
|
|||
|
|
|||
|
function findMatchesInObject (obj, crit, strategy, opt) {
|
|||
|
for (const key in obj) {
|
|||
|
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
|
|||
|
return obj
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isExcluded (term, excludedTerms) {
|
|||
|
for (let i = 0, len = excludedTerms.length; i < len; i++) {
|
|||
|
const excludedTerm = excludedTerms[i]
|
|||
|
if (new RegExp(excludedTerm).test(term)) {
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
return false
|
|||
|
}
|
|||
|
|
|||
|
/* globals ActiveXObject:false */
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$JSONLoader_2 = {
|
|||
|
load: load
|
|||
|
}
|
|||
|
|
|||
|
function load (location, callback) {
|
|||
|
const xhr = getXHR()
|
|||
|
xhr.open('GET', location, true)
|
|||
|
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
|
|||
|
xhr.send()
|
|||
|
}
|
|||
|
|
|||
|
function createStateChangeListener (xhr, callback) {
|
|||
|
return function () {
|
|||
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
|||
|
try {
|
|||
|
callback(null, JSON.parse(xhr.responseText))
|
|||
|
} catch (err) {
|
|||
|
callback(err, null)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function getXHR () {
|
|||
|
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$OptionsValidator_3 = function OptionsValidator (params) {
|
|||
|
if (!validateParams(params)) {
|
|||
|
throw new Error('-- OptionsValidator: required options missing')
|
|||
|
}
|
|||
|
|
|||
|
if (!(this instanceof OptionsValidator)) {
|
|||
|
return new OptionsValidator(params)
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = params.required
|
|||
|
|
|||
|
this.getRequiredOptions = function () {
|
|||
|
return requiredOptions
|
|||
|
}
|
|||
|
|
|||
|
this.validate = function (parameters) {
|
|||
|
const errors = []
|
|||
|
requiredOptions.forEach(function (requiredOptionName) {
|
|||
|
if (typeof parameters[requiredOptionName] === 'undefined') {
|
|||
|
errors.push(requiredOptionName)
|
|||
|
}
|
|||
|
})
|
|||
|
return errors
|
|||
|
}
|
|||
|
|
|||
|
function validateParams (params) {
|
|||
|
if (!params) {
|
|||
|
return false
|
|||
|
}
|
|||
|
return typeof params.required !== 'undefined' && params.required instanceof Array
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
'use strict'
|
|||
|
|
|||
|
var _$utils_9 = {
|
|||
|
merge: merge,
|
|||
|
isJSON: isJSON
|
|||
|
}
|
|||
|
|
|||
|
function merge (defaultParams, mergeParams) {
|
|||
|
const mergedOptions = {}
|
|||
|
for (const option in defaultParams) {
|
|||
|
mergedOptions[option] = defaultParams[option]
|
|||
|
if (typeof mergeParams[option] !== 'undefined') {
|
|||
|
mergedOptions[option] = mergeParams[option]
|
|||
|
}
|
|||
|
}
|
|||
|
return mergedOptions
|
|||
|
}
|
|||
|
|
|||
|
function isJSON (json) {
|
|||
|
try {
|
|||
|
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
|
|||
|
return true
|
|||
|
}
|
|||
|
return false
|
|||
|
} catch (err) {
|
|||
|
return false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var _$src_8 = {};
|
|||
|
(function (window) {
|
|||
|
'use strict'
|
|||
|
|
|||
|
let options = {
|
|||
|
searchInput: null,
|
|||
|
resultsContainer: null,
|
|||
|
json: [],
|
|||
|
success: Function.prototype,
|
|||
|
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
|
|||
|
templateMiddleware: Function.prototype,
|
|||
|
sortMiddleware: function () {
|
|||
|
return 0
|
|||
|
},
|
|||
|
noResultsText: 'No results found',
|
|||
|
limit: 10,
|
|||
|
fuzzy: false,
|
|||
|
debounceTime: null,
|
|||
|
exclude: []
|
|||
|
}
|
|||
|
|
|||
|
let debounceTimerHandle
|
|||
|
const debounce = function (func, delayMillis) {
|
|||
|
if (delayMillis) {
|
|||
|
clearTimeout(debounceTimerHandle)
|
|||
|
debounceTimerHandle = setTimeout(func, delayMillis)
|
|||
|
} else {
|
|||
|
func.call()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
|
|||
|
|
|||
|
/* removed: const _$Templater_7 = require('./Templater') */;
|
|||
|
/* removed: const _$Repository_4 = require('./Repository') */;
|
|||
|
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
|
|||
|
const optionsValidator = _$OptionsValidator_3({
|
|||
|
required: requiredOptions
|
|||
|
})
|
|||
|
/* removed: const _$utils_9 = require('./utils') */;
|
|||
|
|
|||
|
window.SimpleJekyllSearch = function (_options) {
|
|||
|
const errors = optionsValidator.validate(_options)
|
|||
|
if (errors.length > 0) {
|
|||
|
throwError('You must specify the following required options: ' + requiredOptions)
|
|||
|
}
|
|||
|
|
|||
|
options = _$utils_9.merge(options, _options)
|
|||
|
|
|||
|
_$Templater_7.setOptions({
|
|||
|
template: options.searchResultTemplate,
|
|||
|
middleware: options.templateMiddleware
|
|||
|
})
|
|||
|
|
|||
|
_$Repository_4.setOptions({
|
|||
|
fuzzy: options.fuzzy,
|
|||
|
limit: options.limit,
|
|||
|
sort: options.sortMiddleware,
|
|||
|
exclude: options.exclude
|
|||
|
})
|
|||
|
|
|||
|
if (_$utils_9.isJSON(options.json)) {
|
|||
|
initWithJSON(options.json)
|
|||
|
} else {
|
|||
|
initWithURL(options.json)
|
|||
|
}
|
|||
|
|
|||
|
const rv = {
|
|||
|
search: search
|
|||
|
}
|
|||
|
|
|||
|
typeof options.success === 'function' && options.success.call(rv)
|
|||
|
return rv
|
|||
|
}
|
|||
|
|
|||
|
function initWithJSON (json) {
|
|||
|
_$Repository_4.put(json)
|
|||
|
registerInput()
|
|||
|
}
|
|||
|
|
|||
|
function initWithURL (url) {
|
|||
|
_$JSONLoader_2.load(url, function (err, json) {
|
|||
|
if (err) {
|
|||
|
throwError('failed to get JSON (' + url + ')')
|
|||
|
}
|
|||
|
initWithJSON(json)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function emptyResultsContainer () {
|
|||
|
options.resultsContainer.innerHTML = ''
|
|||
|
}
|
|||
|
|
|||
|
function appendToResultsContainer (text) {
|
|||
|
options.resultsContainer.innerHTML += text
|
|||
|
}
|
|||
|
|
|||
|
function registerInput () {
|
|||
|
options.searchInput.addEventListener('input', function (e) {
|
|||
|
if (isWhitelistedKey(e.which)) {
|
|||
|
emptyResultsContainer()
|
|||
|
debounce(function () { search(e.target.value) }, options.debounceTime)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
function search (query) {
|
|||
|
if (isValidQuery(query)) {
|
|||
|
emptyResultsContainer()
|
|||
|
render(_$Repository_4.search(query), query)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function render (results, query) {
|
|||
|
const len = results.length
|
|||
|
if (len === 0) {
|
|||
|
return appendToResultsContainer(options.noResultsText)
|
|||
|
}
|
|||
|
for (let i = 0; i < len; i++) {
|
|||
|
results[i].query = query
|
|||
|
appendToResultsContainer(_$Templater_7.compile(results[i]))
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function isValidQuery (query) {
|
|||
|
return query && query.length > 0
|
|||
|
}
|
|||
|
|
|||
|
function isWhitelistedKey (key) {
|
|||
|
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
|
|||
|
}
|
|||
|
|
|||
|
function throwError (message) {
|
|||
|
throw new Error('SimpleJekyllSearch --- ' + message)
|
|||
|
}
|
|||
|
})(window)
|
|||
|
|
|||
|
}());
|
|||
|
</script>
|
|||
|
|
|||
|
<!-- Configuration -->
|
|||
|
<script>
|
|||
|
SimpleJekyllSearch({
|
|||
|
searchInput: document.getElementById('search-input'),
|
|||
|
resultsContainer: document.getElementById('results-container'),
|
|||
|
noResultsText: '<p>Aucun résultat!</p>',
|
|||
|
json: '/search.json',
|
|||
|
searchResultTemplate: '<li><a href="{url}">{date} {title}</a> (Création {create})</li>'
|
|||
|
})
|
|||
|
</script>
|
|||
|
|
|||
|
</div></div>
|
|||
|
|
|||
|
|
|||
|
<script>(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function scrollToAnchor(anchor, duration, callback) {
|
|||
|
var $root = this;
|
|||
|
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
|
|||
|
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
|
|||
|
callback && callback();
|
|||
|
});
|
|||
|
}
|
|||
|
$.fn.scrollToAnchor = scrollToAnchor;
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function affix(options) {
|
|||
|
var $root = this, $window = $(window), $scrollTarget, $scroll,
|
|||
|
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
|
|||
|
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
|
|||
|
hasInit = false, curState;
|
|||
|
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
|
|||
|
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
|
|||
|
_options.scroll && (scroll = _options.scroll);
|
|||
|
_options.disabled !== undefined && (disabled = _options.disabled);
|
|||
|
$scrollTarget = $(scrollTarget);
|
|||
|
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
|
|||
|
$scroll = $(scroll);
|
|||
|
}
|
|||
|
function preCalc() {
|
|||
|
top();
|
|||
|
rootHeight = $root.outerHeight();
|
|||
|
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
|
|||
|
rootLeft = $root.offset().left;
|
|||
|
}
|
|||
|
function calc(needPreCalc) {
|
|||
|
needPreCalc && preCalc();
|
|||
|
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
|
|||
|
rootBottomTop = scrollBottom - rootTop;
|
|||
|
}
|
|||
|
function top() {
|
|||
|
if (curState !== 'top') {
|
|||
|
$root.removeClass('fixed').css({
|
|||
|
left: 0,
|
|||
|
top: 0
|
|||
|
});
|
|||
|
curState = 'top';
|
|||
|
}
|
|||
|
}
|
|||
|
function fixed() {
|
|||
|
if (curState !== 'fixed') {
|
|||
|
$root.addClass('fixed').css({
|
|||
|
left: rootLeft + 'px',
|
|||
|
top: 0
|
|||
|
});
|
|||
|
curState = 'fixed';
|
|||
|
}
|
|||
|
}
|
|||
|
function bottom() {
|
|||
|
if (curState !== 'bottom') {
|
|||
|
$root.removeClass('fixed').css({
|
|||
|
left: 0,
|
|||
|
top: rootBottomTop + 'px'
|
|||
|
});
|
|||
|
curState = 'bottom';
|
|||
|
}
|
|||
|
}
|
|||
|
function setState() {
|
|||
|
var scrollTop = $scrollTarget.scrollTop();
|
|||
|
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
|
|||
|
fixed();
|
|||
|
} else if (scrollTop < rootTop) {
|
|||
|
top();
|
|||
|
} else {
|
|||
|
bottom();
|
|||
|
}
|
|||
|
}
|
|||
|
function init() {
|
|||
|
if(!hasInit) {
|
|||
|
var interval, timeout;
|
|||
|
calc(true); setState();
|
|||
|
// run calc every 100 millisecond
|
|||
|
interval = setInterval(function() {
|
|||
|
calc();
|
|||
|
}, 100);
|
|||
|
timeout = setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
}, 45000);
|
|||
|
window.pageLoad.then(function() {
|
|||
|
setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
clearTimeout(timeout);
|
|||
|
}, 3000);
|
|||
|
});
|
|||
|
$scrollTarget.on('scroll', function() {
|
|||
|
disabled || setState();
|
|||
|
});
|
|||
|
$window.on('resize', function() {
|
|||
|
disabled || (calc(true), setState());
|
|||
|
});
|
|||
|
hasInit = true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
setOptions(options);
|
|||
|
if (!disabled) {
|
|||
|
init();
|
|||
|
}
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
init();
|
|||
|
}, 200));
|
|||
|
return {
|
|||
|
setOptions: setOptions,
|
|||
|
refresh: function() {
|
|||
|
calc(true, { animation: false }); setState();
|
|||
|
}
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.affix = affix;
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
function toc(options) {
|
|||
|
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
|
|||
|
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
|
|||
|
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
|
|||
|
|
|||
|
function setOptions(options) {
|
|||
|
var _options = options || {};
|
|||
|
_options.selectors && (selectors = _options.selectors);
|
|||
|
_options.container && (container = _options.container);
|
|||
|
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
|
|||
|
_options.scroller && (scroller = _options.scroller);
|
|||
|
_options.disabled !== undefined && (disabled = _options.disabled);
|
|||
|
$headings = $(container).find(selectors).filter('[id]');
|
|||
|
$scrollTarget = $(scrollTarget);
|
|||
|
$scroller = $(scroller);
|
|||
|
}
|
|||
|
function calc() {
|
|||
|
headingsPos = [];
|
|||
|
$headings.each(function() {
|
|||
|
headingsPos.push(Math.floor($(this).position().top));
|
|||
|
});
|
|||
|
}
|
|||
|
function setState(element, disabled) {
|
|||
|
var scrollTop = $scrollTarget.scrollTop(), i;
|
|||
|
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
|
|||
|
if (element) {
|
|||
|
$activeCur = element;
|
|||
|
} else {
|
|||
|
for (i = 0; i < headingsPos.length; i++) {
|
|||
|
if (scrollTop >= headingsPos[i]) {
|
|||
|
$activeCur = $tocLi.eq(i);
|
|||
|
} else {
|
|||
|
$activeCur || ($activeCur = $tocLi.eq(i));
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
$activeLast && $activeLast.removeClass('active');
|
|||
|
($activeLast = $activeCur).addClass('active');
|
|||
|
}
|
|||
|
function render() {
|
|||
|
if(!hasRendered) {
|
|||
|
$root.append($tocUl);
|
|||
|
$headings.each(function() {
|
|||
|
var $this = $(this);
|
|||
|
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
|
|||
|
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
|
|||
|
});
|
|||
|
$tocLi = $tocUl.children('li');
|
|||
|
$tocUl.on('click', 'a', function(e) {
|
|||
|
e.preventDefault();
|
|||
|
var $this = $(this);
|
|||
|
scrolling = true;
|
|||
|
setState($this.parent());
|
|||
|
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
|
|||
|
scrolling = false;
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
hasRendered = true;
|
|||
|
}
|
|||
|
function init() {
|
|||
|
var interval, timeout;
|
|||
|
if(!hasInit) {
|
|||
|
render(); calc(); setState(null, scrolling);
|
|||
|
// run calc every 100 millisecond
|
|||
|
interval = setInterval(function() {
|
|||
|
calc();
|
|||
|
}, 100);
|
|||
|
timeout = setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
}, 45000);
|
|||
|
window.pageLoad.then(function() {
|
|||
|
setTimeout(function() {
|
|||
|
clearInterval(interval);
|
|||
|
clearTimeout(timeout);
|
|||
|
}, 3000);
|
|||
|
});
|
|||
|
$scrollTarget.on('scroll', function() {
|
|||
|
disabled || setState(null, scrolling);
|
|||
|
});
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
if (!disabled) {
|
|||
|
render(); calc(); setState(null, scrolling);
|
|||
|
}
|
|||
|
}, 100));
|
|||
|
}
|
|||
|
hasInit = true;
|
|||
|
}
|
|||
|
|
|||
|
setOptions(options);
|
|||
|
if (!disabled) {
|
|||
|
init();
|
|||
|
}
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
init();
|
|||
|
}, 200));
|
|||
|
return {
|
|||
|
setOptions: setOptions
|
|||
|
};
|
|||
|
}
|
|||
|
$.fn.toc = toc;
|
|||
|
});
|
|||
|
})();
|
|||
|
/*(function () {
|
|||
|
|
|||
|
})();*/
|
|||
|
</script><script>
|
|||
|
/* toc must before affix, since affix need to konw toc' height. */(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $window = $(window);
|
|||
|
var $articleContent = $('.js-article-content');
|
|||
|
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
|
|||
|
var toc;
|
|||
|
var tocDisabled = false;
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
|
|||
|
|
|||
|
function disabled() {
|
|||
|
return $col2.css('display') === 'none' || !hasToc;
|
|||
|
}
|
|||
|
|
|||
|
tocDisabled = disabled();
|
|||
|
|
|||
|
toc = $tocRoot.toc({
|
|||
|
selectors: TOC_SELECTOR,
|
|||
|
container: $articleContent,
|
|||
|
scrollTarget: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroller: hasSidebar ? '.js-page-main' : null,
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
tocDisabled = disabled();
|
|||
|
toc && toc.setOptions({
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
}, 100));
|
|||
|
|
|||
|
});
|
|||
|
})();
|
|||
|
(function() {
|
|||
|
var SOURCES = window.TEXT_VARIABLES.sources;
|
|||
|
window.Lazyload.js(SOURCES.jquery, function() {
|
|||
|
var $window = $(window), $pageFooter = $('.js-page-footer');
|
|||
|
var $pageAside = $('.js-page-aside');
|
|||
|
var affix;
|
|||
|
var tocDisabled = false;
|
|||
|
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
|
|||
|
|
|||
|
affix = $pageAside.affix({
|
|||
|
offsetBottom: $pageFooter.outerHeight(),
|
|||
|
scrollTarget: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroller: hasSidebar ? '.js-page-main' : null,
|
|||
|
scroll: hasSidebar ? $('.js-page-main').children() : null,
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
|
|||
|
$window.on('resize', window.throttle(function() {
|
|||
|
affix && affix.setOptions({
|
|||
|
disabled: tocDisabled
|
|||
|
});
|
|||
|
}, 100));
|
|||
|
|
|||
|
window.pageAsideAffix = affix;
|
|||
|
});
|
|||
|
})();
|
|||
|
</script><!---->
|
|||
|
|
|||
|
</div>
|
|||
|
<script>(function () {
|
|||
|
var $root = document.getElementsByClassName('root')[0];
|
|||
|
if (window.hasEvent('touchstart')) {
|
|||
|
$root.dataset.isTouch = true;
|
|||
|
document.addEventListener('touchstart', function(){}, false);
|
|||
|
}
|
|||
|
})();
|
|||
|
</script>
|
|||
|
</body>
|
|||
|
</html>
|
|||
|
|