3485 lines
268 KiB
HTML
3485 lines
268 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>HETZNER VPS CX21 4Go RAM 40Go SSD debian 10 yunohost (yanfi.space,yanfi.net et cinay.eu) - YannStatic</title>
|
|||
|
|
|||
|
<meta name="description" content="">
|
|||
|
<link rel="canonical" href="https://static.rnmkcy.eu/2020/11/22/VPS-Hetzner-CX21-4GoRam-40GoSSD_debian_10.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;">HETZNER VPS CX21 4Go RAM 40Go SSD debian 10 yunohost (yanfi.space,yanfi.net et cinay.eu)</h1></header></div><meta itemprop="headline" content="HETZNER VPS CX21 4Go RAM 40Go SSD debian 10 yunohost (yanfi.space,yanfi.net et cinay.eu)"><div class="article__info clearfix"><ul class="left-col menu"><li>
|
|||
|
<a class="button button--secondary button--pill button--sm"
|
|||
|
href="/archive.html?tag=vps">vps</a>
|
|||
|
</li><li>
|
|||
|
<a class="button button--secondary button--pill button--sm"
|
|||
|
href="/archive.html?tag=serveur">serveur</a>
|
|||
|
</li></ul><ul class="right-col menu"><li>
|
|||
|
<i class="far fa-calendar-alt"></i> <span title="Création" style="color:#FF00FF">22 nov. 2020</span>
|
|||
|
|
|||
|
<span title="Modification" style="color:#00FF7F">27 sept. 2021</span></li></ul></div><meta itemprop="datePublished" content="2021-09-27T00:00:00+02:00">
|
|||
|
<meta itemprop="keywords" content="vps,serveur"><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><p><a href="https://www.hetzner.com/cloud-fr"><img src="/images/HetznerLogo.png" alt="HETZNER" /></a></p>
|
|||
|
|
|||
|
<h2 id="debian-10-cx21">debian-10-cx21</h2>
|
|||
|
|
|||
|
<p><img src="/images/debian-buster-logo1.png" alt="Debian Buster" height="40" /> <img src="/images/hetzner-cx21.png" alt="HETZNER" height="40" /></p>
|
|||
|
|
|||
|
<p>PARAMETRES D’ACCES:<br />
|
|||
|
L’adresse IPv4 du VPS est : 95.216.222.127<br />
|
|||
|
L’adresse IPv6 du VPS est : 2a01:4f9:c010:45b3::/64<br />
|
|||
|
Hostname : debian-4gb-hel1-1</p>
|
|||
|
|
|||
|
<p>Le nom du VPS est : debian-10-cx21<br />
|
|||
|
La clé publique <strong>debian-10-cx21.pub</strong> est transmise au gestionnaire pour la construction du serveur
|
|||
|
Connexion SSH en “root” avec clés SSH <strong>debian-10-cx21</strong> sans mot de passe</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh -i .ssh/debian-10-cx21 root@95.216.222.127
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Créer mot de passe “root”</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>passwd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Réseau</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 1000
|
|||
|
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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
|
|||
|
link/ether 96:00:00:80:22:12 brd ff:ff:ff:ff:ff:ff
|
|||
|
inet 95.216.222.127/32 brd 95.216.222.127 scope global dynamic eth0
|
|||
|
valid_lft 85731sec preferred_lft 85731sec
|
|||
|
inet6 2a01:4f9:c010:45b3::2255/64 scope global
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
inet6 fe80::9400:ff:fe80:2212/64 scope link
|
|||
|
valid_lft forever preferred_lft forever
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Noyau et OS : <code class="language-plaintext highlighter-rouge">uname -a</code></p>
|
|||
|
|
|||
|
<p>Linux debian-4gb-hel1-1 4.19.0-12-amd64 #1 SMP Debian 4.19.152-1 (2020-10-18) x86_64 GNU/Linux</p>
|
|||
|
|
|||
|
<p>Paramétrage fuseau <strong>Europe/Paris</strong> : <code class="language-plaintext highlighter-rouge">dpkg-reconfigure tzdata</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Current default time zone: 'Europe/Paris'
|
|||
|
Local time is now: Sun Nov 22 08:06:42 CET 2020.
|
|||
|
Universal Time is now: Sun Nov 22 07:06:42 UTC 2020.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier l’heure</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>timedatectl status
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Local time: Sun 2020-11-22 08:45:34 CET
|
|||
|
Universal time: Sun 2020-11-22 07:45:34 UTC
|
|||
|
RTC time: Sun 2020-11-22 07:45:35
|
|||
|
Time zone: Europe/Paris (CET, +0100)
|
|||
|
System clock synchronized: yes
|
|||
|
NTP service: active
|
|||
|
RTC in local TZ: no
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Hostname</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hostnamectl
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Static hostname: debian-4gb-hel1-1
|
|||
|
Icon name: computer-vm
|
|||
|
Chassis: vm
|
|||
|
Machine ID: 5e93c746b78b49c5a61470c448d04423
|
|||
|
Boot ID: 513fff3bb1db43a392217d19105e2c2d
|
|||
|
Virtualization: kvm
|
|||
|
Operating System: Debian GNU/Linux 10 (buster)
|
|||
|
Kernel: Linux 4.19.0-12-amd64
|
|||
|
Architecture: x86-64
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Locales</strong> reconfiguration pour le français par défaut</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dpkg-reconfigure locales
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[*] en_US.UTF-8 UTF-8
|
|||
|
[*] fr_FR.UTF-8 UTF-8
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="yunohost">Yunohost</h2>
|
|||
|
|
|||
|
<p><img src="/images/yunohost.png" alt="" width="30" /></p>
|
|||
|
|
|||
|
<h3 id="installation">Installation</h3>
|
|||
|
|
|||
|
<p>Une fois que vous avez accès à votre serveur (directement ou par SSH)<br />
|
|||
|
vous pouvez installer YunoHost en exécutant cette commande en tant que root :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update && apt upgrade
|
|||
|
apt install curl
|
|||
|
curl https://install.yunohost.org | bash
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span>...]
|
|||
|
<span class="o">[</span> OK <span class="o">]</span> YunoHost installation completed <span class="o">!</span>
|
|||
|
<span class="o">===============================================================================</span>
|
|||
|
You should now proceed with Yunohost post-installation. This is where you will
|
|||
|
be asked <span class="k">for</span> :
|
|||
|
- the main domain of your server <span class="p">;</span>
|
|||
|
- the administration password.
|
|||
|
|
|||
|
You can perform this step :
|
|||
|
- from the <span class="nb">command </span>line, by running <span class="s1">'yunohost tools postinstall'</span> as root
|
|||
|
- or from your web browser, by accessing :
|
|||
|
- https://95.216.222.127/ <span class="o">(</span>global IP, <span class="k">if </span>you<span class="s1">'re on a VPS)
|
|||
|
|
|||
|
If this is your first time with YunoHost, it is strongly recommended to take
|
|||
|
time to read the administator documentation and in particular the sections
|
|||
|
'</span>Finalizing your setup<span class="s1">' and '</span>Getting to know YunoHost<span class="s1">'. It is available at
|
|||
|
the following URL : https://yunohost.org/admindoc
|
|||
|
===============================================================================
|
|||
|
</span></code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="post-installation-yanfispace">Post-installation (yanfi.space)</h3>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost tools postinstall
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Main domain: yanfi.space
|
|||
|
[...]
|
|||
|
Warning: The ssh configuration has been manually modified, but you need to explicitly specify category 'ssh' with --force to actually apply the changes.
|
|||
|
Success! YunoHost is now configured
|
|||
|
Warning: The post-install completed! To finalize your setup, please consider:
|
|||
|
- adding a first user through the 'Users' section of the webadmin (or 'yunohost user create <username>' in command-line);
|
|||
|
- diagnose potential issues through the 'Diagnosis' section of the webadmin (or 'yunohost diagnosis run' in command-line);
|
|||
|
- reading the 'Finalizing your setup' and 'Getting to know Yunohost' parts in the admin documentation: https://yunohost.org/admindoc.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Le mot de passe root remplacé par celui de l’admin yunohost</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3 id="ssh-admin">SSH (admin)</h3>
|
|||
|
|
|||
|
<p><img src="/images/ssh-logo2.png" alt="" width="50" /></p>
|
|||
|
|
|||
|
<p>Autoriser admin à se connecter SSH</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir /home/admin/.ssh
|
|||
|
cp /root/.ssh/authorized_keys /home/admin/.ssh/
|
|||
|
chown admin.1007 -R /home/admin/.ssh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modification SSH pour être conforme à l’installation yunohost mise à part l’utilisation d’un fichier clé qui n’est pas pris en compte dans la gestion SSH Yunohost</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/ssh/sshd_config
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># This configuration has been automatically generated
|
|||
|
# by YunoHost
|
|||
|
|
|||
|
Protocol 2
|
|||
|
Port 55127
|
|||
|
|
|||
|
ListenAddress ::
|
|||
|
ListenAddress 0.0.0.0
|
|||
|
|
|||
|
|
|||
|
HostKey /etc/ssh/ssh_host_ecdsa_key
|
|||
|
HostKey /etc/ssh/ssh_host_ed25519_key
|
|||
|
HostKey /etc/ssh/ssh_host_rsa_key
|
|||
|
|
|||
|
# ##############################################
|
|||
|
# Stuff recommended by Mozilla "modern" compat'
|
|||
|
# https://infosec.mozilla.org/guidelines/openssh
|
|||
|
# ##############################################
|
|||
|
|
|||
|
|
|||
|
# By default use "modern" Mozilla configuration
|
|||
|
# Keys, ciphers and MACS
|
|||
|
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
|
|||
|
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
|
|||
|
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
|
|||
|
|
|||
|
|
|||
|
# LogLevel VERBOSE logs user's key fingerprint on login.
|
|||
|
# Needed to have a clear audit track of which key was using to log in.
|
|||
|
SyslogFacility AUTH
|
|||
|
LogLevel VERBOSE
|
|||
|
|
|||
|
# #######################
|
|||
|
# Authentication settings
|
|||
|
# #######################
|
|||
|
|
|||
|
# Comment from Mozilla about the motivation behind disabling root login
|
|||
|
#
|
|||
|
# Root login is not allowed for auditing reasons. This is because it's difficult to track which process belongs to which root user:
|
|||
|
#
|
|||
|
# On Linux, user sessions are tracking using a kernel-side session id, however, this session id is not recorded by OpenSSH.
|
|||
|
# Additionally, only tools such as systemd and auditd record the process session id.
|
|||
|
# On other OSes, the user session id is not necessarily recorded at all kernel-side.
|
|||
|
# Using regular users in combination with /bin/su or /usr/bin/sudo ensure a clear audit track.
|
|||
|
|
|||
|
LoginGraceTime 120
|
|||
|
PermitRootLogin no
|
|||
|
StrictModes yes
|
|||
|
PubkeyAuthentication yes
|
|||
|
PermitEmptyPasswords no
|
|||
|
ChallengeResponseAuthentication no
|
|||
|
UsePAM yes
|
|||
|
|
|||
|
# Change to no to disable tunnelled clear text passwords
|
|||
|
# (i.e. everybody will need to authenticate using ssh keys)
|
|||
|
PasswordAuthentication no
|
|||
|
|
|||
|
# Post-login stuff
|
|||
|
Banner /etc/issue.net
|
|||
|
PrintMotd no
|
|||
|
PrintLastLog yes
|
|||
|
ClientAliveInterval 60
|
|||
|
AcceptEnv LANG LC_*
|
|||
|
|
|||
|
# Disallow user without ssh or sftp permissions
|
|||
|
AllowGroups ssh.main sftp.main ssh.app sftp.app admins root
|
|||
|
|
|||
|
# Allow users to create tunnels or forwarding
|
|||
|
AllowTcpForwarding yes
|
|||
|
AllowStreamLocalForwarding yes
|
|||
|
PermitTunnel yes
|
|||
|
PermitUserRC yes
|
|||
|
|
|||
|
# SFTP stuff
|
|||
|
Subsystem sftp internal-sftp
|
|||
|
|
|||
|
# Apply following instructions to user with sftp perm only
|
|||
|
Match Group sftp.main,!ssh.main
|
|||
|
ForceCommand internal-sftp
|
|||
|
# We can't restrict to /home/%u because the chroot base must be owned by root
|
|||
|
# So we chroot only on /home
|
|||
|
# See https://serverfault.com/questions/584986/bad-ownership-or-modes-for-chroot-directory-component
|
|||
|
ChrootDirectory /home
|
|||
|
# Forbid SFTP users from using their account SSH as a VPN (even if SSH login is disabled)
|
|||
|
AllowTcpForwarding no
|
|||
|
AllowStreamLocalForwarding no
|
|||
|
PermitTunnel no
|
|||
|
# Disable .ssh/rc, which could be edited (e.g. from Nextcloud or whatever) by users to execute arbitrary commands even if SSH login is disabled
|
|||
|
PermitUserRC no
|
|||
|
|
|||
|
Match Group sftp.app,!ssh.app
|
|||
|
ForceCommand internal-sftp
|
|||
|
ChrootDirectory %h
|
|||
|
AllowTcpForwarding no
|
|||
|
AllowStreamLocalForwarding no
|
|||
|
PermitTunnel no
|
|||
|
PermitUserRC no
|
|||
|
PasswordAuthentication yes
|
|||
|
|
|||
|
# root login is allowed on local networks
|
|||
|
# It's meant to be a backup solution in case LDAP is down and
|
|||
|
# user admin can't be used...
|
|||
|
# If the server is a VPS, it's expected that the owner of the
|
|||
|
# server has access to a web console through which to log in.
|
|||
|
Match Address 192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,169.254.0.0/16,fe80::/10,fd00::/8
|
|||
|
PermitRootLogin yes
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relancer openSSH</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart sshd
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ouvrir le port 55127 et fermer le port 22</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost firewall allow TCP 55127
|
|||
|
yunohost firewall disallow TCP 22
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Accès utilisateur depuis le poste distant avec la clé privée</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh admin@95.216.222.127 -p 55127 -i /home/yannick/.ssh/debian-10-cx21
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer utilitaires</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install rsync curl tmux jq figlet git dnsutils tree -y
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>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-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ___ _
|
|||
|
___ ___ ___ ___ __ __ __|_ <span class="o">)</span>/ | ___ ___ ___ ___
|
|||
|
|___||___||___||___| / _|<span class="se">\ \ </span>/ / / | | |___||___||___||___|
|
|||
|
<span class="se">\_</span>_|/_<span class="se">\_\/</span>___||_|
|
|||
|
_ _ __ _ _ _ / _|<span class="o">(</span>_<span class="o">)</span> ___ _ __ __ _ __ ___
|
|||
|
| <span class="o">||</span> |/ _<span class="sb">`</span> <span class="o">||</span> <span class="s1">' \ | _|| | _ (_-<| '</span>_ <span class="se">\/</span> _<span class="sb">`</span> |/ _|/ <span class="nt">-_</span><span class="o">)</span>
|
|||
|
<span class="se">\_</span>, |<span class="se">\_</span>_,_||_||_||_| _|_|<span class="o">(</span>_<span class="o">)</span>/__/| .__/<span class="se">\_</span>_,_|<span class="se">\_</span>_|<span class="se">\_</span>__|
|
|||
|
|__/ _ __ _ _ _ / _|<span class="o">(</span>_<span class="o">)</span> _|_| ___ | |_
|
|||
|
| <span class="o">||</span> |/ _<span class="sb">`</span> <span class="o">||</span> <span class="s1">' \ | _|| | _ | '</span> <span class="se">\ </span>/ <span class="nt">-_</span><span class="o">)</span>| _|
|
|||
|
<span class="se">\_</span>, |<span class="se">\_</span>_,_||_||_||_| |_|<span class="o">(</span>_<span class="o">)</span>|_||_|<span class="se">\_</span>__| <span class="se">\_</span>_|
|
|||
|
|__/<span class="o">(</span>_<span class="o">)</span> _ _ __ _ _ _ ___ _ _
|
|||
|
/ _|| <span class="o">||</span> <span class="s1">' \ / _` || || | _ / -_)| || |
|
|||
|
\__||_||_||_|\__,_| \_, |(_)\___| \_,_|
|
|||
|
|__/
|
|||
|
</span></code></pre></div></div>
|
|||
|
|
|||
|
<p>Autoriser utilisateur à accéder aux journaux systemd</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo usermod -a -G systemd-journal $USER
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="ssh---alerte-par-messagerie">SSH - Alerte par messagerie</h3>
|
|||
|
|
|||
|
<p><strong>alerte email quand une connexion ssh est réussie</strong></p>
|
|||
|
|
|||
|
<p class="warning">Attention: selon les commentaires, cela ne fonctionnera pas si l’utilisateur crée un fichier nommé <code class="language-plaintext highlighter-rouge">~/.ssh/rc</code></p>
|
|||
|
|
|||
|
<p>Modifier ou créer <code class="language-plaintext highlighter-rouge">/etc/ssh/sshrc</code> avec le contenu suivant:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>DESTINATAIRE="vps@ciany.eu"
|
|||
|
VPHOST=$(hostname -f)
|
|||
|
DATE=$(date "+%d.%m.%Y--%Hh%Mm")
|
|||
|
IP=$(echo $SSH_CONNECTION | awk '{print $1}')
|
|||
|
#IP=`echo $SSH_CONNECTION | cut -d " " -f 1`
|
|||
|
LOCALISATION=$(curl -s ipinfo.io/"$IP" | jq -r '[.country, .city] | join(", ")')
|
|||
|
REVERSE=$(dig -x $IP +short)
|
|||
|
echo "Connexion de ${USER} sur $VPHOST
|
|||
|
|
|||
|
IP de connexion: ${IP}
|
|||
|
Localisation appelant: ${LOCALISATION}
|
|||
|
ReverseDNS: ${REVERSE}
|
|||
|
Date: ${DATE}
|
|||
|
" | mail -s "Connexion de ${USER} sur $VPHOST" $DESTINATAIRE
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="sshfs-partage-xoyazxyz">SSHFS partage xoyaz.xyz</h3>
|
|||
|
|
|||
|
<p><img src="/images/sshfs-logo.png" alt="" width="70" /></p>
|
|||
|
|
|||
|
<p><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>Le but, créer un accès réseau sur un autre serveur pour les gros volumes de fichiers (musique, livres, etc…)<br />
|
|||
|
Le dossier local <strong>/opt/sshfs/</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mkdir -p /opt/sshfs
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Il faut créer une liaison réseau sécurisée entre <strong>cinay.eu ← → xoyaz.xyz</strong></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><strong>Partage avec serveur hms.xoyaz.xyz</strong> : Clé privée <strong>hms-sto-250</strong> <br />
|
|||
|
Droits : <code class="language-plaintext highlighter-rouge">chmod 600 /home/admin/.ssh/hms-sto-250</code></p>
|
|||
|
|
|||
|
<p><strong>Montage 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 userhms@hms.xoyaz.xyz:/home/userhms/sshfs /opt/sshfs -C -p 55051 -oIdentityFile=/home/admin/.ssh/hms-sto-250
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>NOTE: Il faut mettre l’adresse IP du serveur , si les domaines peuvent ne pas être “résolus”</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>Après vérification , <code class="language-plaintext highlighter-rouge">ls /opt/sshfs</code> , déconnexion <code class="language-plaintext highlighter-rouge">fusermount -u /opt/sshfs</code></p>
|
|||
|
|
|||
|
<p><strong>Montage auto</strong><br />
|
|||
|
Ajouter la ligne suivante au fichier <code class="language-plaintext highlighter-rouge">/etc/fstab</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>userhms@hms.xoyaz.xyz:/home/userhms/sshfs /opt/sshfs fuse.sshfs _netdev,identityfile=/home/admin/.ssh/hms-sto-250,allow_other,port=55051 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>
|
|||
|
|
|||
|
<hr />
|
|||
|
<p><strong>OBSOLETE</strong><br />
|
|||
|
<strong>Partage avec serveur xoyaz.xyz</strong><br />
|
|||
|
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/admin/.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@xoyaz.xyz:/home/usernl/backup /opt/sshfs -C -p 55036 -oIdentityFile=/home/admin/.ssh/OVZ-STORAGE-128
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The authenticity of host <span class="s1">'[xoyaz.xyz]:55036 ([2a04:52c0:101:82::73db]:55036)'</span> can<span class="s1">'t be established.
|
|||
|
ECDSA key fingerprint is SHA256:NuFqR5id10fVzRLsSTqJ4vBpFnNYi+APGsvPYth6PHw.
|
|||
|
Are you sure you want to continue connecting (yes/no)? yes
|
|||
|
</span></code></pre></div></div>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>NOTE: Il faut mettre l’adresse IP du serveur , si les domaines peuvent ne pas être “résolus”</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>Après vérification , <code class="language-plaintext highlighter-rouge">ls /opt/sshfs</code> , déconnexion <code class="language-plaintext highlighter-rouge">fusermount -u /opt/sshfs</code></p>
|
|||
|
|
|||
|
<p><strong>Montage fstab</strong></p>
|
|||
|
|
|||
|
<p>ajouter les lignes suivantes au fichier <strong>/etc/fstab</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>usernl@xoyaz.xyz:/home/usernl/backup /opt/sshfs fuse.sshfs _netdev,identityfile=/home/admin/.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>
|
|||
|
|
|||
|
<hr />
|
|||
|
|
|||
|
<h3 id="domaines-et-dns">Domaines et DNS</h3>
|
|||
|
|
|||
|
<p><img src="/images/dns-logo.png" alt="" width="50" /></p>
|
|||
|
|
|||
|
<p>Configuration DNS domaine par défaut <strong>yanfi.space</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain dns-conf yanfi.space
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>; Basic ipv4/ipv6 records
|
|||
|
@ 3600 IN A 95.216.222.127
|
|||
|
@ 3600 IN AAAA 2a01:4f9:c010:45b3::2255
|
|||
|
|
|||
|
; XMPP
|
|||
|
_xmpp-client._tcp 3600 IN SRV 0 5 5222 yanfi.space.
|
|||
|
_xmpp-server._tcp 3600 IN SRV 0 5 5269 yanfi.space.
|
|||
|
muc 3600 IN CNAME @
|
|||
|
pubsub 3600 IN CNAME @
|
|||
|
vjud 3600 IN CNAME @
|
|||
|
xmpp-upload 3600 IN CNAME @
|
|||
|
|
|||
|
; Mail
|
|||
|
@ 3600 IN MX 10 yanfi.space.
|
|||
|
@ 3600 IN TXT "v=spf1 a mx -all"
|
|||
|
mail._domainkey 3600 IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM7ja2oZ0efNg8WWoRY82kneRiJOciFAgyBfaDpNzRQdaphq082256m6Ol9tWEqCjWakO5nmvP03s+zw53lZoUfZyY4FE58AAesHszSyvVYhCz7uSfEijD4snvIYSqkuFvRNLv2WCYPQFelx9VPl5095f+8X0Y8dx4H2TvGGqsUQIDAQAB"
|
|||
|
_dmarc 3600 IN TXT "v=DMARC1; p=none"
|
|||
|
|
|||
|
; Extra
|
|||
|
* 3600 IN A 95.216.222.127
|
|||
|
* 3600 IN AAAA 2a01:4f9:c010:45b3::2255
|
|||
|
@ 3600 IN CAA 128 issue "letsencrypt.org"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Se connecter à l’espace client du site OVH : <strong>Web cloud → Domaines → xoyize.xyz → Zone DNS</strong><br />
|
|||
|
Cliquer sur <strong>“Modifier en mode textuel”</strong>, garder les 4 premières lignes :<br />
|
|||
|
<img src="/images/dns-ovh-zone.png" alt="" width="600" /><br />
|
|||
|
puis effacer tout ce qu’il y a en-dessous, et le remplacer par la configuration donnée par votre serveur ( <code class="language-plaintext highlighter-rouge">yunohost domain dns-conf</code>)</p>
|
|||
|
|
|||
|
<p>Création et configuration DNS domaine <strong>yanfi.net</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain add yanfi.net
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les dns</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain dns-conf yanfi.net
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>; Basic ipv4/ipv6 records
|
|||
|
@ 3600 IN A 95.216.222.127
|
|||
|
@ 3600 IN AAAA 2a01:4f9:c010:45b3::2255
|
|||
|
|
|||
|
; XMPP
|
|||
|
_xmpp-client._tcp 3600 IN SRV 0 5 5222 yanfi.net.
|
|||
|
_xmpp-server._tcp 3600 IN SRV 0 5 5269 yanfi.net.
|
|||
|
muc 3600 IN CNAME @
|
|||
|
pubsub 3600 IN CNAME @
|
|||
|
vjud 3600 IN CNAME @
|
|||
|
xmpp-upload 3600 IN CNAME @
|
|||
|
|
|||
|
; Mail
|
|||
|
@ 3600 IN MX 10 yanfi.net.
|
|||
|
@ 3600 IN TXT "v=spf1 a mx -all"
|
|||
|
mail._domainkey 3600 IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7jDcuICl4E9fLUhdum1TW7Pxj+pKDrn7np1nu4umYuZd7qVt69JGjtF4RvBGOASxguG1uVZLoBBYPgA8sZmmbT1Laf7g74YQm+i345yjzklT96aCJu1PvZMosvzMOBfbx6N08Nav5Rp++PTuMHFXhyDmJMr/c2/epVWm4eXbdAwIDAQAB"
|
|||
|
_dmarc 3600 IN TXT "v=DMARC1; p=none"
|
|||
|
|
|||
|
; Extra
|
|||
|
* 3600 IN A 95.216.222.127
|
|||
|
* 3600 IN AAAA 2a01:4f9:c010:45b3::2255
|
|||
|
@ 3600 IN CAA 128 issue "letsencrypt.org"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Création et configuration DNS domaine <strong>cinay.eu</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain add cinay.eu
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les dns</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain dns-conf cinay.eu
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>; Basic ipv4/ipv6 records
|
|||
|
@ 3600 IN A 95.216.222.127
|
|||
|
@ 3600 IN AAAA 2a01:4f9:c010:45b3::2255
|
|||
|
|
|||
|
; XMPP
|
|||
|
_xmpp-client._tcp 3600 IN SRV 0 5 5222 cinay.eu.
|
|||
|
_xmpp-server._tcp 3600 IN SRV 0 5 5269 cinay.eu.
|
|||
|
muc 3600 IN CNAME @
|
|||
|
pubsub 3600 IN CNAME @
|
|||
|
vjud 3600 IN CNAME @
|
|||
|
xmpp-upload 3600 IN CNAME @
|
|||
|
|
|||
|
; Mail
|
|||
|
@ 3600 IN MX 10 cinay.eu.
|
|||
|
@ 3600 IN TXT "v=spf1 a mx -all"
|
|||
|
mail._domainkey 3600 IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDn4KD67wSLqb4ACbBdFniSYnPkbNHAjCdah4fYFuyVkefSW5lZjmwPiZ26GJpf1gBT4/kUc5XtRdXosCDJuGsmfq0JwA7813Gmn00wNIuOGQ5WglGSvpm73iVomF/psI/+ElbA0TX0T8babIciq+jdA7g4ZhJ/zUX93oAAOoqaOQIDAQAB"
|
|||
|
_dmarc 3600 IN TXT "v=DMARC1; p=none"
|
|||
|
|
|||
|
; Extra
|
|||
|
* 3600 IN A 95.216.222.127
|
|||
|
* 3600 IN AAAA 2a01:4f9:c010:45b3::2255
|
|||
|
@ 3600 IN CAA 128 issue "letsencrypt.org"
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="reverse-dns-hetzner-vps-cx21">Reverse DNS HETZNER VPS CX21</h3>
|
|||
|
|
|||
|
<p>Se connecter en console sur l’hébergeur du VPS et dans Networking , modifier les reverses DNS</p>
|
|||
|
|
|||
|
<p>Mise à jour reverse DNS IPV4 IPV6<br />
|
|||
|
95.216.222.127 → yanfi.space<br />
|
|||
|
2a01:4f9:c010:45b3::2255 → yanfi.space</p>
|
|||
|
|
|||
|
<h3 id="certificats-ssl">Certificats SSL</h3>
|
|||
|
|
|||
|
<p><img src="/images/letsencrypt-logo1.png" alt="" /></p>
|
|||
|
|
|||
|
<p>Installer un certificat Let’s Encrypt en ligne de commande</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain cert-install --no-checks # yanfi.space
|
|||
|
yunohost domain cert-install yanfi.net --no-checks
|
|||
|
yunohost domain cert-install cinay.eu --no-checks
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="utilisateur-yann">Utilisateur yann</h3>
|
|||
|
|
|||
|
<p>Création utilisateur yann</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost user create yann
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>First name: yann
|
|||
|
Last name: cinayeu
|
|||
|
E-mail address: yann@cinay.eu
|
|||
|
You are now about to define a new user password. The password should be at least 8 characters long—though it is good practice to use a longer password (i.e. a passphrase) and/or to a variation of characters (uppercase, lowercase, digits and special characters).
|
|||
|
Password:
|
|||
|
Confirm password:
|
|||
|
Success! User created
|
|||
|
fullname: yann cinayeu
|
|||
|
mail: yann@cinay.eu
|
|||
|
username: yann
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="historique-de-la-ligne-de-commande">Historique de la ligne de commande</h3>
|
|||
|
|
|||
|
<p>Ajoutez la recherche d’historique de la ligne de commande au terminal.
|
|||
|
Tapez un début de commande précédent, puis utilisez shift + up (flèche haut) pour rechercher l’historique filtré avec le début de la commande.</p>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Global, tout utilisateur</span>
|
|||
|
<span class="nb">echo</span> <span class="s1">'"\e[1;2A": history-search-backward'</span> | <span class="nb">sudo tee</span> <span class="nt">-a</span> /etc/inputrc
|
|||
|
<span class="nb">echo</span> <span class="s1">'"\e[1;2B": history-search-forward'</span> | <span class="nb">sudo tee</span> <span class="nt">-a</span> /etc/inputrc
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="script-ssh_rc_bash">Script ssh_rc_bash</h3>
|
|||
|
|
|||
|
<p><img src="/images/bash-shell-logo.png" alt="" width="50" /></p>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p><strong>ATTENTION!!! Les scripts sur connexion peuvent poser des problèmes pour des appels externes autres que ssh</strong></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wget https://static.xoyaz.xyz/files/ssh_rc_bash
|
|||
|
chmod +x ssh_rc_bash # rendre le bash exécutable
|
|||
|
./ssh_rc_bash # exécution
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><img src="/images/cx21.png" alt="" /></p>
|
|||
|
|
|||
|
<h2 id="applications">Applications</h2>
|
|||
|
|
|||
|
<p class="info">La plupart des commandes sont exécutées en mode “su”</p>
|
|||
|
|
|||
|
<h3 id="nextcloud-nextcloud">Nextcloud (/nextcloud)</h3>
|
|||
|
|
|||
|
<p><img src="/images/nextcloud_logo.png" alt="" width="70" /></p>
|
|||
|
|
|||
|
<p>Sur le domaine cinay.eu admin, yann</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/nextcloud_ynh --debug
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[...]
|
|||
|
Choose a domain for Nextcloud (default: cinay.eu):
|
|||
|
Choose a path for Nextcloud (default: /nextcloud):
|
|||
|
|
|||
|
Choose the Nextcloud administrator (must be an existing YunoHost user): yann
|
|||
|
Access the users home folder from Nextcloud? [yes | no] (default: no): no
|
|||
|
[...]
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Dans les paramètres fichier de nextcloud , activer l’affichage des fichiers masqués</p>
|
|||
|
|
|||
|
<h4 id="activer-les-applications">Activer les applications</h4>
|
|||
|
|
|||
|
<p>Activer les applications <strong>Calendar</strong>, <strong>Contacts</strong> et <strong>Notes</strong> sur nextcloud</p>
|
|||
|
|
|||
|
<h4 id="paramètres-de-base">Paramètres de base</h4>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Paramètres de base
|
|||
|
<ul>
|
|||
|
<li>Serveur e-mail</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li>Personnaliser l’apparence
|
|||
|
<ul>
|
|||
|
<li>Logo</li>
|
|||
|
<li>Image de connexion</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h4 id="calendrier-et-contacts-android-et-thunderbird">Calendrier et contacts (android et thunderbird)</h4>
|
|||
|
|
|||
|
<p>Paramétrage <strong>OpenSync</strong> android<br />
|
|||
|
Connexion avec le lien https://cinay.eu/nextcloud/remote.php/dav (login+mdp)<br />
|
|||
|
<img src="/images/opensync-1.png" alt="" height="300" /> <img src="/images/opensync-2.png" alt="" height="300" /></p>
|
|||
|
|
|||
|
<p>Paramétrer les applications qui utilisent le calendrier et les contacts<br />
|
|||
|
<strong>Contacts</strong> , <strong>acalendar</strong> et <strong>Tâches</strong><br />
|
|||
|
<img src="/images/opensync-3.png" alt="" height="300" /> <img src="/images/opensync-4.png" alt="" height="300" /> <img src="/images/opensync-5.png" alt="" height="300" /></p>
|
|||
|
|
|||
|
<p>Paramétrage agenda <strong>Thunderbird</strong><br />
|
|||
|
<img src="/images/thb001.png" alt="" width="300" /> <img src="/images/thb002.png" alt="" width="300" /><br />
|
|||
|
<img src="/images/thb003.png" alt="" width="300" /> <img src="/images/thb004.png" alt="" width="300" />
|
|||
|
<img src="/images/thb005.png" alt="" width="300" /><br />
|
|||
|
Se désabonner de l’ancien agenda cinay.xyz</p>
|
|||
|
|
|||
|
<p>Paramétrage contacts <strong>Thunderbird</strong><br />
|
|||
|
Outils → Préférences des modules → TbSync <br />
|
|||
|
Dans l’application<br />
|
|||
|
Actions sur les comptes → Ajouter un nouveau compte → Caldav & Carddav<br />
|
|||
|
<img src="/images/tbsync01.png" alt="" width="300" /> <img src="/images/tbsync02.png" alt="" width="300" /> <br />
|
|||
|
<img src="/images/tbsync03.png" alt="" width="300" /> <br />
|
|||
|
<img src="/images/tbsync04.png" alt="" width="300" /> <br />
|
|||
|
Synchronisation toutes les heures pour les contacts</p>
|
|||
|
|
|||
|
<p>Liens caldav carddav sur thunderbird (yann) <br />
|
|||
|
https://cinay.eu/nextcloud/remote.php/dav/calendars/yann/personal/<br />
|
|||
|
https://cinay.eu/nextcloud/remote.php/dav/addressbooks/users/yann/contacts/</p>
|
|||
|
|
|||
|
<h4 id="compte-nextcloud-sur-les-postes-clients-de-type-pc">Compte nextcloud sur les postes clients de type PC</h4>
|
|||
|
|
|||
|
<p>Ajout du compte https://cinay.eu/nextcloud sur les clients nextcloud <br />
|
|||
|
Synchronisations:</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>~/.keepassx → Home/.keepassx (créer le dossier)</li>
|
|||
|
<li>~/media/Notes → Notes (créer le dossier)</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h4 id="compte-nextcloud-sur-android">Compte nextcloud sur android</h4>
|
|||
|
|
|||
|
<p>Application nextcloud installée<br />
|
|||
|
Se connecter https://cinay.eu/nextcloud et vérifier la création du compte<br />
|
|||
|
<img src="/images/ncinayeu001.png" alt="" height="300" /></p>
|
|||
|
|
|||
|
<p>Synchroniser le fichier de mot de passe avec l’application keepass<br />
|
|||
|
<img src="/images/ncinayeu002.png" alt="" height="300" /> <img src="/images/ncinayeu003.png" alt="" height="300" /><br />
|
|||
|
<img src="/images/ncinayeu004.png" alt="" width="200" /></p>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>Corriger l’avertissement <font color="red">« La limite de mémoire PHP est inférieure à la valeur recommandée de 512 Mo »</font><br />
|
|||
|
Augmenter la mémoire : <code class="language-plaintext highlighter-rouge">memory_limit = 512M</code> dans le fichier <code class="language-plaintext highlighter-rouge">/etc/php/7.3/fpm/php.ini</code> <br />
|
|||
|
Relancer <code class="language-plaintext highlighter-rouge">sudo systemctl restart php7.3-fpm</code></p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3 id="tiny-tiny-rss-ttrss">Tiny Tiny RSS (/ttrss)</h3>
|
|||
|
|
|||
|
<p><img src="/images/ttrss-logo.png" alt="image" width="50px" /><br />
|
|||
|
<em>Tiny Tiny RSS (ttrss) est un agrégateur de flux RSS et Atom libre sous licence libre GNU GPL v3</em></p>
|
|||
|
|
|||
|
<p>Installation en mode de commande (su)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install ttrss
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Choose a domain for Tiny-Tiny-RSS (default: cinay.eu):
|
|||
|
Choose a path for Tiny-Tiny-RSS (default: /ttrss):
|
|||
|
Success! Installation completed
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Mise à jour</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app upgrade ttrss -u https://github.com/YunoHost-Apps/ttrss_ynh/tree/testing --debug
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Personnaliser le CSS , configuration</p>
|
|||
|
|
|||
|
<p><img src="/images/ttrss-css1.png" alt="" width="400" /></p>
|
|||
|
|
|||
|
<p>Ajout du contenu suivant dans la feuille de style</p>
|
|||
|
|
|||
|
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">body</span><span class="nc">.flat.ttrss_main</span> <span class="nf">#headlines-frame</span> <span class="nc">.hl.Unread</span><span class="nd">:not</span><span class="o">(</span><span class="nc">.active</span><span class="o">)</span><span class="nd">:not</span><span class="o">(</span><span class="nc">.Selected</span><span class="o">),</span>
|
|||
|
<span class="nt">body</span><span class="nc">.flat.ttrss_main</span> <span class="nf">#headlines-frame</span> <span class="nc">.cdm.expandable.Unread</span><span class="nd">:not</span><span class="o">(</span><span class="nc">.active</span><span class="o">)</span><span class="nd">:not</span><span class="o">(</span><span class="nc">.Selected</span><span class="o">)</span> <span class="p">{</span>
|
|||
|
<span class="nl">background</span><span class="p">:</span> <span class="m">#696969</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><img src="/images/ttrss-css2.png" alt="" width="400" /><br />
|
|||
|
Puis cliquer <strong>Save and reload</strong></p>
|
|||
|
|
|||
|
<h3 id="shaarli">Shaarli</h3>
|
|||
|
|
|||
|
<p><img src="/images/shaarli_logo.png" alt="" width="70" /></p>
|
|||
|
|
|||
|
<p>Installation</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/shaarli_ynh/tree/testing
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>domaine : yanfi.space
|
|||
|
racine : /shaarli
|
|||
|
utilisateur admin : yann
|
|||
|
Mp admin : idem mp yann
|
|||
|
Site publique: oui
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Basculer l’application de privée en publique</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sed -i "s/is_public\: '0'/is_public\: '1'/g" /etc/yunohost/apps/shaarli/settings.yml
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Regénérer la configuration</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app ssowatconf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="staticcinayeu">static.cinay.eu</h3>
|
|||
|
|
|||
|
<p>En mode su</p>
|
|||
|
|
|||
|
<p>Créer le domaine static.cinay.eu et les certificats</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain add static.cinay.eu
|
|||
|
yunohost domain cert-install static.cinay.eu --no-checks
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer l’application <code class="language-plaintext highlighter-rouge">Custom web app</code> sur le domaine static.cinay.eu</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/my_webapp_ynh/tree/testing --debug
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Domaine : static.cinay.eu<br />
|
|||
|
Racine : /<br />
|
|||
|
Utilisateur : yann<br />
|
|||
|
Create a database: no<br />
|
|||
|
Site publique: yes<br />
|
|||
|
SFTP : no + mot de passe</p>
|
|||
|
|
|||
|
<p>Accès au site https://static.cinay.eu</p>
|
|||
|
|
|||
|
<p>Le dossier <strong>/opt/sshfs/static/</strong> contient le site statique qui est issu d’une synchronisation d’un conteneur debian sur un ordinateur archlinux avec jekyll comme générateur</p>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">rm</span> <span class="nt">-r</span> /var/www/my_webapp/www/ <span class="c"># supprimer dossier web </span>
|
|||
|
<span class="nb">chown </span>my_webapp.my_webapp <span class="nt">-R</span> /var/www/my_webapp
|
|||
|
<span class="nb">ln</span> <span class="nt">-s</span> /opt/sshfs/static /var/www/my_webapp/www <span class="c"># lien et droits my_webapp</span>
|
|||
|
<span class="nb">ln</span> <span class="nt">-s</span> /opt/sshfs/static/htmldoc /var/www/my_webapp/www/htmldoc
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier l’étiquette <code class="language-plaintext highlighter-rouge">my_webapp</code> (static.cinay.eu)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app change-label my_webapp 'Statique static.cinay.eu'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="cinayeusite">cinay.eu/site</h3>
|
|||
|
|
|||
|
<p>Accès à des liens tel que “Diceware”<br />
|
|||
|
<em>Le diceware, ou méthode du lancer de dés selon l’ Office québécois de la langue française, est, en cryptologie, une méthode employée pour créer des phrases secrètes, des mots de passe et d’autres variables cryptographiques en utilisant un dé ordinaire à six faces comme générateur de nombres aléatoires physique.</em></p>
|
|||
|
|
|||
|
<p>Installer l’application <code class="language-plaintext highlighter-rouge">Custom web app</code> sans sftp sur cinay.eu/site</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/my_webapp_ynh/tree/testing --debug
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Application id: my_webapp__2</p>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">rm</span> <span class="nt">-r</span> /var/www/my_webapp__2/www <span class="c"># supprimer dossier web </span>
|
|||
|
<span class="nb">chown </span>my_webapp__2.my_webapp__2 <span class="nt">-R</span> /var/www/my_webapp__2
|
|||
|
<span class="nb">ln</span> <span class="nt">-s</span> /opt/sshfs/www /var/www/my_webapp__2/www <span class="c"># lien et droits my_webapp</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier le fichier de configuration <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/cinay.eu.d/my_webapp__2.conf</code> pour lister le contenu d’un répertoire</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> # Deny access to hidden files and directories
|
|||
|
# location ~ ^/site/(.+/|)\.(?!well-known\/) {
|
|||
|
# deny all;
|
|||
|
# }
|
|||
|
|
|||
|
fancyindex on; # Enable fancy indexes.
|
|||
|
fancyindex_exact_size off; # Output human-readable file sizes.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Redémarrer le serveur nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart nginx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier l’étiquette <code class="language-plaintext highlighter-rouge">my_webapp__2</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app change-label my_webapp__2 'Cartographie Diceware'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>https://cinay.eu/site</p>
|
|||
|
|
|||
|
<p><img src="/images/cinay.eu_site.png" alt="" width="500" /></p>
|
|||
|
|
|||
|
<h3 id="cartes---mapcinayeu">Cartes - map.cinay.eu</h3>
|
|||
|
|
|||
|
<p>En mode su</p>
|
|||
|
|
|||
|
<p>Créer le domaine map.cinay.eu et les certificats</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain add map.cinay.eu
|
|||
|
yunohost domain cert-install map.cinay.eu --no-checks
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer l’application <code class="language-plaintext highlighter-rouge">Custom web app</code> sur le domaine map.cinay.eu</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/my_webapp_ynh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Choose the domain where this app should be installed [cinay.eu | gitea.cinay.eu | map.cinay.eu | static.cinay.eu | yanfi.net | yanfi.space | searx.yanfi.space | zic.yanfi.space] (default: yanfi.space): map.cinay.eu
|
|||
|
Choose the path where this app should be installed (default: /site): /
|
|||
|
Do you need a SFTP access? [yes | no] (default: yes): no
|
|||
|
Choose an administration password for this app:
|
|||
|
Should this app be exposed to anonymous visitors? [yes | no] (default: yes):
|
|||
|
Do you need a MySQL database? [yes | no] (default: no):
|
|||
|
[...]
|
|||
|
Info: [####################] > Installation of my_webapp__3 completed
|
|||
|
Success! Installation completed
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Accès au site https://map.cinay.eu</p>
|
|||
|
|
|||
|
<p>Le dossier <strong>/opt/sshfs/www/osm-new/</strong> contient le site cartographique basé sur leaflet</p>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">rm</span> <span class="nt">-r</span> /var/www/my_webapp__3/www/ <span class="c"># supprimer dossier web </span>
|
|||
|
<span class="nb">chown </span>my_webapp__3.my_webapp__3 <span class="nt">-R</span> /var/www/my_webapp__3
|
|||
|
<span class="nb">ln</span> <span class="nt">-s</span> /opt/sshfs/www/osm-new /var/www/my_webapp__3/www <span class="c"># lien et droits my_webapp__3</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier l’étiquette <code class="language-plaintext highlighter-rouge">my_webapp__3</code> (map.cinay.eu)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app change-label my_webapp__3 'Cartes map.cinay.eu'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="gitea-giteacinayeu">Gitea (gitea.cinay.eu)</h3>
|
|||
|
|
|||
|
<p><a href="https://github.com/YunoHost-Apps/gitea_ynh"><img src="/images/gitea-logo.png" alt="" width="70" /></a></p>
|
|||
|
|
|||
|
<p>Ajout domaine et certificats gitea.cinay.eu</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain add gitea.cinay.eu
|
|||
|
yunohost domain cert-install gitea.cinay.eu --no-checks
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installation à partir de github, on clône le dépôt</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/YunoHost-Apps/gitea_ynh.git
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Blocage sur fail2ban à l’installation <br />
|
|||
|
Commenter la mise en place FAIL2BAN</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano gitea_ynh/scripts/install
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># SETUP FAIL2BAN
|
|||
|
#ynh_script_progression --message="Configuring fail2ban..."
|
|||
|
#ynh_add_fail2ban_config --logpath "/var/log/$app/gitea.log" --failregex ".*Failed authentication attempt for .* from <HOST>" --max_retry 5
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer gitea</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install gitea_ynh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Fail2ban , règle qui n’est pas ajouté</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ynh_add_fail2ban_config --logpath /var/log/gitea/gitea.log --failregex '.*Failed authentication attempt for .* from <HOST>' --max_retry 5
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier l’étiquette <code class="language-plaintext highlighter-rouge">gitea</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app change-label gitea 'Gitea gitea.cinay.eu'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="searx-searxyanfispace">Searx (searx.yanfi.space)</h3>
|
|||
|
|
|||
|
<p><a href="https://github.com/YunoHost-Apps/searx_ynh"><img src="/images/Searx_logo.png" alt="" width="50" /></a></p>
|
|||
|
|
|||
|
<p>Ajout domaine et certificats searx.yanfi.space</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo yunohost domain add searx.yanfi.space
|
|||
|
sudo yunohost domain cert-install searx.yanfi.space --no-checks
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Searx - docker</strong><br />
|
|||
|
Les procédures d’installation, voir le lien <a href="/2018/05/03/Searx-Metamoteur-Recherche-Libre.html">Searx (métamoteur de recherche libre)</a></p>
|
|||
|
|
|||
|
<p>L’image du docker est <a href="https://hub.docker.com/r/searx/searx">searx/searx</a> (basée sur <a href="https://github.com/searx/searx">github.com/searx/searx</a>).</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /home/admin
|
|||
|
docker pull searx/searx
|
|||
|
docker images
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>REPOSITORY TAG IMAGE ID CREATED SIZE
|
|||
|
searx/searx latest 096886989dad 6 hours ago 161MB
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>La méthode la plus simple pour déployer un conteneur en tant que service consiste à créer le conteneur s’il n’existe pas avec un nom donné et ensuite de mapper chacune des opérations de docker (démarrage et arrêt) aux commandes de service du système.</p>
|
|||
|
|
|||
|
<p>Une fois que nous avons créé ce conteneur, nous pouvons le démarrer, l’arrêter et le redémarrer en utilisant les commandes habituelles du docker en indiquant le nom du conteneur (<code class="language-plaintext highlighter-rouge">docker stop searx</code>, <code class="language-plaintext highlighter-rouge">docker start searx</code>, <code class="language-plaintext highlighter-rouge">docker restart searx</code>).</p>
|
|||
|
|
|||
|
<p>Créer un nouveau fichier d’unité systemd <code class="language-plaintext highlighter-rouge">searx.service</code> avec la description du service dans <code class="language-plaintext highlighter-rouge">/etc/systemd/system/</code>.</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/systemd/system/searx.service
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Unit]
|
|||
|
Description=searx container
|
|||
|
After=docker.service
|
|||
|
Wants=network-online.target docker.socket
|
|||
|
Requires=docker.socket
|
|||
|
|
|||
|
[Service]
|
|||
|
Restart=always
|
|||
|
ExecStartPre=/bin/bash -c "/usr/bin/docker container inspect searx 2> /dev/null || /usr/bin/docker run --name searx --rm -d -v /home/admin/searx:/etc/searx -p 8089:8080 -e BASE_URL=http://localhost:8089/ searx/searx"
|
|||
|
ExecStart=/usr/bin/docker start -a searx
|
|||
|
ExecStop=/usr/bin/docker stop -t 10 searx
|
|||
|
|
|||
|
[Install]
|
|||
|
WantedBy=multi-user.target
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Recharger les services</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl daemon-reload
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le fichier d’unité crée un nouveau service et associe les commandes de démarrage et d’arrêt du docker aux séquences de démarrage et d’arrêt du service.</p>
|
|||
|
|
|||
|
<p>Le fichier unit décrit comme des dépendances la cible réseau en ligne et la prise docker, si la prise docker ne démarre pas ce service ne le fera pas non plus. Il ajoute également une dépendance à docker.service, de sorte que ce service ne fonctionnera pas tant que docker.service n’aura pas démarré.</p>
|
|||
|
|
|||
|
<p>Nous pouvons maintenant démarrer/arrêter le service en émettant la commande correspondante :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl start searx # sudo systemctl stop searx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier localement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl --location --verbose --head --insecure localhost:8089
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[...]
|
|||
|
* Trying 127.0.0.1...
|
|||
|
* TCP_NODELAY set
|
|||
|
* Expire in 200 ms for 4 (transfer 0x5614e62aef90)
|
|||
|
* Connected to localhost (127.0.0.1) port 8089 (#0)
|
|||
|
> HEAD / HTTP/1.1
|
|||
|
> Host: localhost:8089
|
|||
|
> User-Agent: curl/7.64.0
|
|||
|
> Accept: */*
|
|||
|
>
|
|||
|
< HTTP/1.1 200 OK
|
|||
|
HTTP/1.1 200 OK
|
|||
|
[...]
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier le fichier de configuration</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano ${PWD}/searx/settings.yml
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>general:
|
|||
|
|
|||
|
instance_name : "yann-searx" # displayed name
|
|||
|
|
|||
|
server:
|
|||
|
base_url : http://localhost:8089/ # Set custom base_url. Possible values: False or "https://your.custom.host/lo
|
|||
|
cation/"
|
|||
|
|
|||
|
ui:
|
|||
|
theme_args :
|
|||
|
oscar_style : logicodev-dark # default style of oscar
|
|||
|
results_on_new_tab: True # Open result links in a new tab by default
|
|||
|
|
|||
|
# supprimer la ligne 'disabled : True' des éléments ci dessous
|
|||
|
|
|||
|
- name : ddg definitions
|
|||
|
engine : duckduckgo_definitions
|
|||
|
shortcut : ddd
|
|||
|
weight : 2
|
|||
|
|
|||
|
- name : duckduckgo
|
|||
|
engine : duckduckgo
|
|||
|
shortcut : ddg
|
|||
|
|
|||
|
- name : duckduckgo images
|
|||
|
engine : duckduckgo_images
|
|||
|
shortcut : ddi
|
|||
|
timeout: 3.0
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Redémarrage pour prise en charge des modifications</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl restart searx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Valider le service pour qu’il fonctionne au démarrage en courant :</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable searx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Pour info, docker ID</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker ps
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
|||
|
dfefa57f88f9 searx/searx "/sbin/tini -- /usr/…" 9 minutes ago Up 9 minutes 0.0.0.0:8089->8080/tcp searx
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Redémarrer le container par son ID : <code class="language-plaintext highlighter-rouge">docker restart dfefa57f88f9</code></p>
|
|||
|
|
|||
|
<p><strong>TEST à partir d’un poste distant</strong> <br />
|
|||
|
Exécuter sur un poste distant</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh -L 9000:localhost:8089 cxuser@135.181.27.140 -p 55140 -i /home/yannick/.ssh/cx11_ed25519
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Sur le même poste , ouvrir le navigateur avec un lien <a href="http://localhost:9000">http://localhost:9000</a></p>
|
|||
|
|
|||
|
<p><img src="/images/cx11-docker-searx.png" alt="Texte alternatif" width="600" /></p>
|
|||
|
|
|||
|
<p><strong>Proxy searx</strong><br />
|
|||
|
Installer application yunohost proxy <strong>redirect</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo yunohost app install https://github.com/YunoHost-Apps/redirect_ynh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Choose a domain for your redirect (default: cinay.eu): searx.yanfi.space
|
|||
|
Choose a path for your redirect (default: /redirect): /
|
|||
|
Redirect destination path (default: http://127.0.0.1): http://127.0.0.1:8089
|
|||
|
Redirect type [public_302 | public_301 | public_proxy | private_proxy] (default: public_302): public_proxy
|
|||
|
Info: Installing redirect...
|
|||
|
[...]
|
|||
|
Success! Installation completed
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier l’étiquette <code class="language-plaintext highlighter-rouge">redirect</code> (searx.cinay.eu)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo yunohost app change-label redirect 'Moteur Recherche searx.cinay.eu'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Accès lien https://searx.yanfi.space</p>
|
|||
|
|
|||
|
<p><strong>Mise à jour de l’image docker searx</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /home/admin
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Télécharge la dernière image searx</p>
|
|||
|
|
|||
|
<table>
|
|||
|
<tbody>
|
|||
|
<tr>
|
|||
|
<td>docker images –format “{{.Repository}}:{{.Tag}}”</td>
|
|||
|
<td>grep ‘:latest’</td>
|
|||
|
<td>xargs -L1 docker pull;</td>
|
|||
|
</tr>
|
|||
|
</tbody>
|
|||
|
</table>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>latest: Pulling from searx/searx
|
|||
|
339de151aab4: Pull <span class="nb">complete
|
|||
|
</span>cb464254eb0a: Pull <span class="nb">complete
|
|||
|
</span>3df700c30092: Pull <span class="nb">complete
|
|||
|
</span>9a4946c2a738: Pull <span class="nb">complete
|
|||
|
</span>2c615ec6f7fa: Pull <span class="nb">complete
|
|||
|
</span>ef48a2d171a2: Pull <span class="nb">complete
|
|||
|
</span>Digest: sha256:b4df2141a868644563f82680d66dc0d3c1d366f598ffc1cdb484d796c117230f
|
|||
|
Status: Downloaded newer image <span class="k">for </span>searx/searx:latest
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Liste des images</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker images
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>REPOSITORY TAG IMAGE ID CREATED SIZE
|
|||
|
searx/searx latest 2b9a1d1fc86a 5 days ago 205MB
|
|||
|
searx/searx <none> 096886989dad 7 months ago 161MB
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Arrêt image searx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl stop searx.service
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Supprimer l’image par ID</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker rmi 096886989dad
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les images restantes</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker images
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>REPOSITORY TAG IMAGE ID CREATED SIZE
|
|||
|
searx/searx latest 2b9a1d1fc86a 5 days ago 205MB
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relancer le service</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl start searx.service
|
|||
|
sudo systemctl status searx.service
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>● searx.service - searx container
|
|||
|
Loaded: loaded <span class="o">(</span>/etc/systemd/system/searx.service<span class="p">;</span> enabled<span class="p">;</span> vendor preset: enabled<span class="o">)</span>
|
|||
|
Active: active <span class="o">(</span>running<span class="o">)</span> since Fri 2021-08-20 18:26:17 CEST<span class="p">;</span> 17s ago
|
|||
|
Process: 15680 <span class="nv">ExecStartPre</span><span class="o">=</span>/bin/bash <span class="nt">-c</span> /usr/bin/docker container inspect searx 2> /dev/null <span class="o">||</span> /usr/bin/docker run <span class="nt">--name</span> sear
|
|||
|
Main PID: 15788 <span class="o">(</span>docker<span class="o">)</span>
|
|||
|
Tasks: 7 <span class="o">(</span>limit: 4579<span class="o">)</span>
|
|||
|
Memory: 21.5M
|
|||
|
CGroup: /system.slice/searx.service
|
|||
|
└─15788 /usr/bin/docker start <span class="nt">-a</span> searx
|
|||
|
|
|||
|
Aug 20 18:26:16 yanfi.space systemd[1]: Starting searx container...
|
|||
|
Aug 20 18:26:16 yanfi.space bash[15680]: <span class="o">[]</span>
|
|||
|
Aug 20 18:26:16 yanfi.space bash[15680]: 6a7551c7a9fbbdc86e234aa07dbadde13ecd2878cef7beea49272b9de2a0b313
|
|||
|
Aug 20 18:26:17 yanfi.space systemd[1]: Started searx container.
|
|||
|
Aug 20 18:26:17 yanfi.space docker[15788]: searx version 1.0.0-200-313a9847
|
|||
|
Aug 20 18:26:17 yanfi.space docker[15788]: Use existing /etc/searx/uwsgi.ini
|
|||
|
Aug 20 18:26:17 yanfi.space docker[15788]: Use existing /etc/searx/settings.yml
|
|||
|
Aug 20 18:26:17 yanfi.space docker[15788]: Listen on 0.0.0.0:8080
|
|||
|
Aug 20 18:26:17 yanfi.space docker[15788]: <span class="o">[</span>uWSGI] getting INI configuration from /etc/searx/uwsgi.ini
|
|||
|
Aug 20 18:26:17 yanfi.space docker[15788]: <span class="o">[</span>uwsgi-static] added mapping <span class="k">for</span> /static <span class="o">=></span> /usr/local/searx/searx/static
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="navidrome-stream-audio">Navidrome (stream audio)</h3>
|
|||
|
|
|||
|
<p><em>Navidrome est un serveur et un streamer de collection de musique en ligne open source. Il vous donne la liberté d’écouter votre playlist à partir de n’importe quel navigateur ou appareil mobile.</em></p>
|
|||
|
|
|||
|
<p>Votre musique est a stockée par default dans le dossier multimédia partagé /home/yunohost.multimedia/share/Music. Ce dossier, facilement accessible depuis Nextcloud avec Stockages externes activée, vous permettra d’uploader facilement vos fichiers de musique sur votre server.</p>
|
|||
|
|
|||
|
<p>Vous pouvez personnaliser le dossier de stockage de vos fichiers de musique en éditant le fichier de configuration <strong>/var/lib/navidrome/navidrome.toml</strong> et rediriger la variable <code class="language-plaintext highlighter-rouge">MusicFolder = "/home/yunohost.multimedia/share/Music"</code>. Vous pouvez également changer d’autre réglage en vous aidant de la <a href="https://www.navidrome.org/docs/usage/configuration-options/">documentation</a>.</p>
|
|||
|
|
|||
|
<p>En mode su</p>
|
|||
|
|
|||
|
<p>Ajout domaine et certificats zic.yanfi.space</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain add zic.yanfi.space
|
|||
|
yunohost domain cert-install zic.yanfi.space --no-checks
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer navidrome</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/navidrome_ynh/tree/testing --debug
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>domaine : zic.yanfi.space<br />
|
|||
|
racine : /<br />
|
|||
|
anonyme : oui</p>
|
|||
|
|
|||
|
<p>Modification fichier de configuration, dossier musique et scan</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano /var/lib/navidrome/navidrome.toml
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Folder where your music library is stored. Can be read-only
|
|||
|
MusicFolder = "/opt/sshfs/musique"
|
|||
|
|
|||
|
# How frequently to scan for changes in your music library. Set it to 0 to disable scans
|
|||
|
ScanSchedule = '@every 24h'
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Redémarrer le service</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart navidrome.service
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier l’étiquette <code class="language-plaintext highlighter-rouge">navidrome</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app change-label navidrome 'Zic Navidrome zic.cinay.eu'
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="rainloop">Rainloop</h3>
|
|||
|
|
|||
|
<p><img src="/images/rainloop1.png" alt="" width="150" /></p>
|
|||
|
|
|||
|
<p>En mode su</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install rainloop
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Choose the domain where this app should be installed [cinay.eu | gitea.cinay.eu | static.cinay.eu | yanfi.net | yanfi.space | searx.yanfi.space | zic.yanfi.space] (default: yanfi.space):
|
|||
|
Choose the path where this app should be installed (default: /rainloop):
|
|||
|
Should this app be exposed to anonymous visitors? [yes | no] (default: no):
|
|||
|
Choose an administration password for this app:
|
|||
|
Do you want to add YunoHost users to the recipients suggestions? [yes | no] (default: yes):
|
|||
|
Select default language [de | en | es | fr | it | pt] (default: en): fr
|
|||
|
[...]
|
|||
|
Info: [####################] > Installation of rainloop completed
|
|||
|
Success! Installation completed
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="librespeed">LibreSpeed</h3>
|
|||
|
|
|||
|
<p><img src="/images/icon_huge.png" alt="LibreSpeed" width="50" /></p>
|
|||
|
|
|||
|
<p><em>Test de vitesse de connexion très léger.<a href="https://fdossena.com/?p=speedtest/index.frag">LibreSpeed</a></em></p>
|
|||
|
|
|||
|
<p>domaine : yanfi.space<br />
|
|||
|
site : /librespeed</p>
|
|||
|
|
|||
|
<p>En mode su</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install librespeed # un mot de passe administartion est demandé
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le fichier de configuration nginx</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/nginx/conf.d/yanfi.space.d/librespeed.conf
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> rewrite ^/librespeed$ /librespeed/ permanent;
|
|||
|
location /librespeed/ {
|
|||
|
|
|||
|
# Path to source
|
|||
|
alias /var/www/librespeed/ ;
|
|||
|
|
|||
|
# Force usage of https
|
|||
|
if ($scheme = http) {
|
|||
|
rewrite ^ https://$server_name$request_uri? permanent;
|
|||
|
}
|
|||
|
|
|||
|
### Example PHP configuration (remove it if not used)
|
|||
|
index yann-singleServer-full.html index.php;
|
|||
|
|
|||
|
# Common parameter to increase upload size limit in conjunction with dedicated php-fpm file
|
|||
|
client_max_body_size 256M;
|
|||
|
|
|||
|
try_files $uri $uri/ /index.php;
|
|||
|
location ~ [^/]\.php(/|$) {
|
|||
|
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
|||
|
fastcgi_pass unix:/var/run/php/php7.3-fpm-librespeed.sock;
|
|||
|
fastcgi_index index.php;
|
|||
|
include fastcgi_params;
|
|||
|
fastcgi_param REMOTE_USER $remote_user;
|
|||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
|||
|
fastcgi_param SCRIPT_FILENAME $request_filename;
|
|||
|
}
|
|||
|
### End of PHP configuration part
|
|||
|
|
|||
|
# Include SSOWAT user panel.
|
|||
|
include conf.d/yunohost_panel.conf.inc;
|
|||
|
}
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p class="info">Le fichier original <code class="language-plaintext highlighter-rouge">example-singleServer-full.html</code> a été remplacé par <code class="language-plaintext highlighter-rouge">yann-singleServer-full.html</code></p>
|
|||
|
|
|||
|
<p>https://yanfi.space/librespeed</p>
|
|||
|
|
|||
|
<h3 id="calibre-ebookyanfispace">Calibre ebook.yanfi.space</h3>
|
|||
|
|
|||
|
<p>Source : https://github.com/janeczku/calibre-web<br />
|
|||
|
Caractéristiques</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>Interface HTML5 Bootstrap 3</li>
|
|||
|
<li>configuration graphique complète</li>
|
|||
|
<li>Gestion des utilisateurs avec des permissions par utilisateur à grain fin</li>
|
|||
|
<li>Interface administrateur</li>
|
|||
|
<li>Interface utilisateur en brésilien, tchèque, néerlandais, anglais, finnois, français, allemand, grec, hongrois, italien, japonais, khmer, polonais, russe, chinois simplifié, espagnol, suédois, turc, ukrainien.</li>
|
|||
|
<li>Flux OPDS pour les applications de lecture de livres électroniques</li>
|
|||
|
<li>Filtrez et recherchez par titres, auteurs, tags, séries et langues.</li>
|
|||
|
<li>Créer une collection de livres personnalisée (étagères)</li>
|
|||
|
<li>Prise en charge de l’édition des métadonnées des livres électroniques et de la suppression des livres électroniques de la bibliothèque Calibre.</li>
|
|||
|
<li>Prise en charge de la conversion des eBooks par les binaires Calibre</li>
|
|||
|
<li>Restriction du téléchargement des livres électroniques aux utilisateurs connectés</li>
|
|||
|
<li>Support pour l’enregistrement public des utilisateurs</li>
|
|||
|
<li>Envoi d’eBooks vers des appareils Kindle d’un simple clic de souris</li>
|
|||
|
<li>Synchronisation de vos appareils Kobo avec votre bibliothèque Calibre via Calibre-Web</li>
|
|||
|
<li>Prise en charge de la lecture des eBooks directement dans le navigateur (.txt, .epub, .pdf, .cbr, .cbt, .cbz, .djvu)</li>
|
|||
|
<li>Téléchargement de nouveaux livres dans de nombreux formats, y compris les formats audio (.mp3, .m4a, .m4b)</li>
|
|||
|
<li>Prise en charge des colonnes personnalisées de Calibre</li>
|
|||
|
<li>Possibilité de masquer le contenu en fonction des catégories et du contenu des colonnes personnalisées par utilisateur.</li>
|
|||
|
<li>Possibilité de mise à jour automatique</li>
|
|||
|
<li>Connexion “Magic Link” pour faciliter la connexion aux eReaders</li>
|
|||
|
<li>Connexion via LDAP, google/github oauth et via l’authentification proxy.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>Ajout domaine et certificats ebook.yanfi.space</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost domain add ebook.yanfi.space
|
|||
|
yunohost domain cert-install ebook.yanfi.space --no-checks
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Installer l’application <strong>Calibre-web</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost app install https://github.com/YunoHost-Apps/calibreweb_ynh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Choose the domain where this app should be installed [cinay.eu | gitea.cinay.eu | map.cinay.eu | static.cinay.eu | yanfi.net | yanfi.space | ebook.yanfi.space | searx.yanfi.space | zic.yanfi.space] (default: yanfi.space): ebook.yanfi.space
|
|||
|
Choose the path where this app should be installed (default: /calibre): /
|
|||
|
Choose an administrator user for this app [yann | claudine | yanfi]: yann
|
|||
|
Should this app be exposed to anonymous visitors? [yes | no] (default: no): yes
|
|||
|
Select a default language [fr | en | es | de] (default: fr):
|
|||
|
Do you want to allow uploading of books? [yes | no] (default: no):
|
|||
|
Do you want to allow access to the library to all Yunohost users? [yes | no] (default: yes):
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>Le dossier des livres</strong> est une copie d’un dossier distant qui est mis à jour une fois par jour<br />
|
|||
|
Synchronisation du dossier local <code class="language-plaintext highlighter-rouge">/home/yunohost.multimedia/share/eBook/</code> avec le dossier distant <code class="language-plaintext highlighter-rouge">/home/usernl/backup/BiblioCalibre</code> du serveur xoyaz.xyz<br />
|
|||
|
L’opération est exécutable en mode su seulement</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rsync -avz --delete --rsync-path="sudo rsync" -e "ssh -p 55051 -i /home/admin/.ssh/hms-sto-250 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" userhms@hms.xoyaz.xyz:/home/userhms/sshfs/BiblioCalibre/* /home/yunohost.multimedia/share/eBook/ && chown calibreweb.calibreweb -R /home/yunohost.multimedia/share/eBook/
|
|||
|
|
|||
|
Créer une tâche crontab
|
|||
|
|
|||
|
sudo crontab -e
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Synchronisation du dossier local /home/yunohost.multimedia/share/eBook/ avec le dossier distant /home/userhms/sshfs/BiblioCalibre du serveur hms.xoyaz.xyz
|
|||
|
# Tous les jours à 4h00 du matin
|
|||
|
0 4 * * * rsync -avz --delete --rsync-path="sudo rsync" -e "ssh -p 55051 -i /home/admin/.ssh/hms-sto-250 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" userhms@hms.xoyaz.xyz:/home/userhms/sshfs/BiblioCalibre/* /home/yunohost.multimedia/share/eBook/ && chown calibreweb.calibreweb -R /home/yunohost.multimedia/share/eBook/
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p class="info">A FAIRE : En cas de modification du dossier /home/userhms/sshfs/BiblioCalibre sur le serveur hms.xoyaz.xyz<br />
|
|||
|
Il faut effectuer une synchro du dossier par rsync depuis le serveur hms.xoyaz.xyz vers yanfi.space</p>
|
|||
|
|
|||
|
<p><strong>Les traductions de l’application “calibreweb_ynh”</strong></p>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>find /var/www/calibreweb/cps/templates/ <span class="nt">-name</span> <span class="s2">"*.*"</span> <span class="nt">-type</span> f <span class="nt">-exec</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"s#'Sort according to book date, newest first'#'Trier selon la date du livre, le plus récent en premier'#g"</span> <span class="o">{}</span> <span class="se">\;</span>
|
|||
|
find /var/www/calibreweb/cps/templates/ <span class="nt">-name</span> <span class="s2">"*.*"</span> <span class="nt">-type</span> f <span class="nt">-exec</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"s#'Sort according to book date, oldest first'#'Trier selon la date du livre, le plus ancien en premier'#g"</span> <span class="o">{}</span> <span class="se">\;</span>
|
|||
|
find /var/www/calibreweb/cps/templates/ <span class="nt">-name</span> <span class="s2">"*.*"</span> <span class="nt">-type</span> f <span class="nt">-exec</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"s#'Sort title in alphabetical order'#'Trier le titre par ordre alphabétique'#g"</span> <span class="o">{}</span> <span class="se">\;</span>
|
|||
|
find /var/www/calibreweb/cps/templates/ <span class="nt">-name</span> <span class="s2">"*.*"</span> <span class="nt">-type</span> f <span class="nt">-exec</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"s#'Sort title in reverse alphabetical order'#'Trier le titre en ordre alphabétique inverse'#g"</span> <span class="o">{}</span> <span class="se">\;</span>
|
|||
|
find /var/www/calibreweb/cps/templates/ <span class="nt">-name</span> <span class="s2">"*.*"</span> <span class="nt">-type</span> f <span class="nt">-exec</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"s#'Sort authors in alphabetical order'#'Trier les auteurs par ordre alphabétique'#g"</span> <span class="o">{}</span> <span class="se">\;</span>
|
|||
|
find /var/www/calibreweb/cps/templates/ <span class="nt">-name</span> <span class="s2">"*.*"</span> <span class="nt">-type</span> f <span class="nt">-exec</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"s#'Sort authors in reverse alphabetical order'#'Trier les auteurs par ordre alphabétique inverse'#g"</span> <span class="o">{}</span> <span class="se">\;</span>
|
|||
|
find /var/www/calibreweb/cps/templates/ <span class="nt">-name</span> <span class="s2">"*.*"</span> <span class="nt">-type</span> f <span class="nt">-exec</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"s#'Sort according to publishing date, newest first'#'Trier selon la date de publication, les plus récentes en premier'#g"</span> <span class="o">{}</span> <span class="se">\;</span>
|
|||
|
find /var/www/calibreweb/cps/templates/ <span class="nt">-name</span> <span class="s2">"*.*"</span> <span class="nt">-type</span> f <span class="nt">-exec</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s2">"s#'Sort according to publishing date, oldest first'#'Trier selon la date de publication, la plus ancienne en premier'#g"</span> <span class="o">{}</span> <span class="se">\;</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Les fichiers de traduction française dans le dossier <code class="language-plaintext highlighter-rouge">/var/www/calibreweb/cps/translations/fr/LC_MESSAGES/</code><br />
|
|||
|
Editer et modifier le fichier <code class="language-plaintext highlighter-rouge">messages.po</code><br />
|
|||
|
Convertir le <code class="language-plaintext highlighter-rouge">po</code> vers <code class="language-plaintext highlighter-rouge">mo</code> , lien <a href="http://po2mo.net/">http://po2mo.net/</a><br />
|
|||
|
Redémarrer le service <code class="language-plaintext highlighter-rouge">calibreweb</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl restart calibreweb
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Ouverture du lien https://ebook.yanfi.space<br />
|
|||
|
<img src="/images/calibre-web3.png" alt="" width="400" /> <img src="/images/calibre-web4.png" alt="" width="400" /></p>
|
|||
|
|
|||
|
<p><img src="/images/calibre-web5.png" alt="" width="400" /> <img src="/images/calibre-web7.png" alt="" width="400" /></p>
|
|||
|
|
|||
|
<p><img src="/images/calibre-web6.png" alt="" width="400" /> <img src="/images/calibre-web8.png" alt="" width="400" /></p>
|
|||
|
|
|||
|
<p><img src="/images/calibre-web9.png" alt="" width="400" /></p>
|
|||
|
|
|||
|
<h2 id="sauvegardes">Sauvegardes</h2>
|
|||
|
|
|||
|
<h3 id="borgbackup">BorgBackup</h3>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li><a href="/2021/09/25/BorgBackup-Client-Serveur.html">BorgBackup client serveur</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3 id="via-rsync">Via rsync</h3>
|
|||
|
|
|||
|
<p class="warning">Sauvegarde complète de yunohost <strong>yanfi.space</strong> sur le serveur <strong>hms.xoyaz.xyz</strong> via <strong>rsync</strong><br />
|
|||
|
est désactivée depuis la mise en place de la sauvegarde par <strong>BorgBackup</strong></p>
|
|||
|
|
|||
|
<p>Créer le bash <code class="language-plaintext highlighter-rouge">~/backup-hms.xoyaz.xyz.sh</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nano ~/backup-hms.xoyaz.xyz.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/sh</span>
|
|||
|
<span class="c"># Créer une sauvegarde totale localement</span>
|
|||
|
yunohost backup create <span class="nt">--debug</span>
|
|||
|
<span class="c"># Copier cette sauvegarde sur le distant hms.xoyaz.xyz</span>
|
|||
|
rsync <span class="nt">-avz</span> <span class="nt">--progress</span> <span class="nt">--stats</span> <span class="nt">--human-readable</span> <span class="nt">--rsync-path</span><span class="o">=</span><span class="s2">"sudo rsync"</span> <span class="nt">-e</span> <span class="s2">"ssh -p 55051 -i /home/admin/.ssh/hms-sto-250 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"</span> /home/yunohost.backup/archives/<span class="si">$(</span><span class="nb">date</span> <span class="s1">'+%Y%m%d'</span><span class="si">)</span><span class="k">*</span> userhms@hms.xoyaz.xyz:/home/userhms/sshfs/yanfi.space/ <span class="p">;</span> <span class="se">\</span>
|
|||
|
<span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> <span class="nt">-eq</span> 0 <span class="o">]</span><span class="p">;</span> <span class="k">then</span> <span class="se">\</span>
|
|||
|
<span class="nb">echo</span> <span class="s2">"Sauvegardes </span><span class="si">$(</span><span class="nb">date</span> <span class="s1">'+%Y%m%d'</span><span class="si">)</span><span class="s2">* -> OK"</span> | systemd-cat <span class="nt">-t</span> allsync <span class="nt">-p</span> info <span class="p">;</span> <span class="se">\</span>
|
|||
|
<span class="nb">rm</span> /home/yunohost.backup/archives/<span class="si">$(</span><span class="nb">date</span> <span class="s1">'+%Y%m%d'</span><span class="si">)</span><span class="k">*</span> <span class="p">;</span> <span class="se">\</span>
|
|||
|
<span class="k">else</span> <span class="se">\</span>
|
|||
|
<span class="nb">echo</span> <span class="s2">"Sauvegardes </span><span class="si">$(</span><span class="nb">date</span> <span class="s1">'+%Y%m%d'</span><span class="si">)</span><span class="s2">* -> ERREUR"</span> | systemd-cat <span class="nt">-t</span> allsync <span class="nt">-p</span> emerg <span class="p">;</span> <span class="se">\</span>
|
|||
|
<span class="k">fi</span>
|
|||
|
</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 ~/backup-hms.xoyaz.xyz.sh
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le résultat de la commande est dans le journal</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>journalctl --no-pager -t allsync --since today
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-- Logs begin at Wed 2021-09-15 11:48:08 CEST, end at Wed 2021-09-15 18:47:50 CEST. --
|
|||
|
Sep 15 18:24:45 yanfi.space allsync[16720]: Sauvegardes 20210915* -> OK
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Tâche</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo crontab -e
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>10 02 * * * /home/admin/backup-hms.xoyaz.xyz.sh > /dev/null
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h2 id="yunohost-">Yunohost +</h2>
|
|||
|
|
|||
|
<h3 id="maintenance">Maintenance</h3>
|
|||
|
|
|||
|
<p><strong>sauvegardes borg sur le serveur xoyaz.yz</strong><br />
|
|||
|
Clé SSH pour lister les sauvegardes borg sur le serveur xoyaz.yz</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh-keygen -t ed25519 -f ~/.ssh/borg_yanfi
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Se connecter au serveur xoyaz.xyz et ajouter la clé publique</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh userhms@45.145.166.51 -p 55051 -i /home/yann/.ssh/hms-sto-250
|
|||
|
sudo -u borgbackup -s # utilisateur borgbackup
|
|||
|
echo 'ssh-ed25519 AAAAkjhreszFJE5AAAAIBWaYu5BvBcpuTeP4/0QXLm3/vmKP7EagcWXi+MGygJ7 yann@archyan' >> /home/backup/.ssh/authorized_keys
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Test connexion SSH</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh borgbackup@xoyaz.xyz -p 55051 -i /home/yann/.ssh/borg_yanfi
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="erreurs-et-avertissements">Erreurs et avertissements</h3>
|
|||
|
|
|||
|
<p>yanfi.space<br />
|
|||
|
Mise à jour reverse DNS IPV4 IPV6<br />
|
|||
|
95.216.222.127 → yanfi.space<br />
|
|||
|
2a01:4f9:c010:45b3::2255 → yanfi.space</p>
|
|||
|
|
|||
|
<p>Mise à jour yunohost 02/02/2021</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost diagnosis run --force
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Le détail</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost diagnosis show --issues
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>reports:
|
|||
|
0:
|
|||
|
description: Base system
|
|||
|
id: basesystem
|
|||
|
items:
|
|||
|
status: WARNING
|
|||
|
summary: It looks like apt (the package manager) is configured to use the backports repository. Unless you really know what you are doing, we strongly discourage from installing packages from backports, because it's likely to create unstabilities or conflicts on your system.
|
|||
|
1:
|
|||
|
description: Email
|
|||
|
id: mail
|
|||
|
items:
|
|||
|
0:
|
|||
|
details:
|
|||
|
- The blacklist reason is: "http://www.barracudanetworks.com/reputation/?pr=1&ip=95.216.222.127"
|
|||
|
- After identifying why you are listed and fixed it, feel free to ask for your IP or domaine to be removed on https://barracudacentral.org/rbl/
|
|||
|
status: ERROR
|
|||
|
summary: Your IP or domain 95.216.222.127 is blacklisted on Barracuda Reputation Block List
|
|||
|
1:
|
|||
|
details:
|
|||
|
- The blacklist reason is: "https://matrix.spfbl.net/2a01:4f9:c010:45b3:0:0:0:1"
|
|||
|
- After identifying why you are listed and fixed it, feel free to ask for your IP or domaine to be removed on https://spfbl.net/en/dnsbl/
|
|||
|
status: ERROR
|
|||
|
summary: Your IP or domain 2a01:4f9:c010:45b3::2255 is blacklisted on SPFBL.net RBL
|
|||
|
2:
|
|||
|
description: System configurations
|
|||
|
id: regenconf
|
|||
|
items:
|
|||
|
details: This is probably OK if you know what you're doing! YunoHost will stop updating this file automatically... But beware that YunoHost upgrades could contain important recommended changes. If you want to, you can inspect the differences with 'yunohost tools regen-conf ssh --dry-run --with-diff' and force the reset to the recommended configuration with 'yunohost tools regen-conf ssh --force'
|
|||
|
status: WARNING
|
|||
|
summary: Configuration file /etc/ssh/sshd_config appears to have been manually modified.
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Email</p>
|
|||
|
|
|||
|
<p><strong>Résoudre le blocage barracuda</strong></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> - The blacklist reason is: "http://www.barracudanetworks.com/reputation/?pr=1&ip=95.216.222.127"
|
|||
|
- After identifying why you are listed and fixed it, feel free to ask for your IP or domaine to be removed on https://barracudacentral.org/rbl/
|
|||
|
status: ERROR
|
|||
|
summary: Your IP or domain 95.216.222.127 is blacklisted on Barracuda Reputation Block List
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Lien <a href="https://barracudacentral.org/rbl/removal-request">https://barracudacentral.org/rbl/removal-request</a> , il faut renseigner l’adresse ip <code class="language-plaintext highlighter-rouge">95.216.222.127</code> et un mail <br />
|
|||
|
Traduction du résultat:</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Demande reçue
|
|||
|
|
|||
|
Merci d'avoir soumis votre demande. S'il s'agit de votre première demande, la réputation de votre adresse IP sera portée à "normale" pendant 48 heures, le temps que nous menions notre enquête. Il peut s'écouler jusqu'à une heure avant que la réputation ne se propage à tous les pare-feu antispam Barracuda dans le monde. Nous vous remercions de votre patience et vous prions de nous excuser pour tout désagrément.
|
|||
|
|
|||
|
Votre numéro de confirmation est BBR21612284433-86752-13901.
|
|||
|
|
|||
|
EmailReg.org
|
|||
|
|
|||
|
Une façon d'éviter que votre courrier électronique soit bloqué par inadvertance est d'enregistrer votre domaine et vos adresses IP sur EmailReg.org. Les courriels provenant de noms de domaine et d'adresses IP correctement enregistrés sur EmailReg.org peuvent être automatiquement exemptés des couches de défense du filtrage du spam sur les pare-feu antispam Barracuda et d'autres solutions antispam, ce qui permet d'éviter que votre courriel soit accidentellement bloqué.
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Résoudre le blocage</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> - The blacklist reason is: "https://matrix.spfbl.net/2a01:4f9:c010:45b3:0:0:0:1"
|
|||
|
- After identifying why you are listed and fixed it, feel free to ask for your IP or domaine to be removed on https://spfbl.net/en/dnsbl/
|
|||
|
status: ERROR
|
|||
|
summary: Your IP or domain 2a01:4f9:c010:45b3::2255 is blacklisted on SPFBL.net RBL
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Vérifier rDNS</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[yann@archyan ~]$ dig ptr 127.222.216.95.in-addr.arpa +noall +answer
|
|||
|
127.222.216.95.in-addr.arpa. 86400 IN PTR yanfi.space.
|
|||
|
[yann@archyan ~]$ dig PTR 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.3.b.5.4.0.1.0.c.9.f.4.0.1.0.a.2.ip6.arpa +noall +answer
|
|||
|
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.3.b.5.4.0.1.0.c.9.f.4.0.1.0.a.2.ip6.arpa. 86400 IN PTR yanfi.space.
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h3 id="thème-yann">Thème “yann”</h3>
|
|||
|
|
|||
|
<p>A partir d’un thème existant : <code class="language-plaintext highlighter-rouge">cp -r /usr/share/ssowat/portal/assets/themes/{light,yann}</code> <br />
|
|||
|
Les images : <code class="language-plaintext highlighter-rouge">/usr/share/ssowat/portal/assets/img/</code><br />
|
|||
|
Image de fond : <code class="language-plaintext highlighter-rouge">iceland-aurore-polaire.jpg</code><br />
|
|||
|
Logo : ym-70x70.png , yannick-white16x16.png <br />
|
|||
|
Le fichier css : <code class="language-plaintext highlighter-rouge">/usr/share/ssowat/portal/assets/themes/yann/custom_portal.css</code><br />
|
|||
|
Modifier la balise <code class="language-plaintext highlighter-rouge">body {</code></p>
|
|||
|
|
|||
|
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">/*
|
|||
|
===============================================================================
|
|||
|
This file contain extra CSS rules to customize the YunoHost user portal and
|
|||
|
can be used to customize app tiles, buttons, etc...
|
|||
|
===============================================================================
|
|||
|
*/</span>
|
|||
|
<span class="nt">body</span> <span class="p">{</span>
|
|||
|
<span class="nl">margin</span><span class="p">:</span><span class="m">0</span><span class="p">;</span>
|
|||
|
<span class="nl">padding</span><span class="p">:</span><span class="m">0</span><span class="p">;</span>
|
|||
|
<span class="nl">background</span><span class="p">:</span> <span class="sx">url("../../img/iceland-aurore-polaire.jpg")</span> <span class="nb">no-repeat</span> <span class="nb">center</span> <span class="nb">fixed</span><span class="p">;</span>
|
|||
|
<span class="nl">-webkit-background-size</span><span class="p">:</span> <span class="n">cover</span><span class="p">;</span> <span class="c">/* pour anciens Chrome et Safari */</span>
|
|||
|
<span class="nl">background-size</span><span class="p">:</span> <span class="n">cover</span><span class="p">;</span> <span class="c">/* version standardisée */</span>
|
|||
|
<span class="p">}</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Personnaliser le logo<br />
|
|||
|
Modifier le fichier <code class="language-plaintext highlighter-rouge">/usr/share/ssowat/portal/assets/themes/yann/custom_portal.css</code></p>
|
|||
|
|
|||
|
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">/* Logo */</span>
|
|||
|
<span class="nc">.ynh-logo</span> <span class="p">{</span>
|
|||
|
<span class="nl">opacity</span><span class="p">:</span> <span class="m">0.7</span><span class="p">;</span>
|
|||
|
<span class="nl">margin-top</span><span class="p">:</span> <span class="m">6em</span><span class="p">;</span>
|
|||
|
<span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
|
|||
|
<span class="nl">height</span><span class="p">:</span> <span class="m">9em</span><span class="p">;</span>
|
|||
|
<span class="nl">background-image</span><span class="p">:</span> <span class="sx">url("../../img/ym-70x70.png")</span><span class="p">;</span>
|
|||
|
<span class="nl">background-repeat</span><span class="p">:</span> <span class="nb">no-repeat</span><span class="p">;</span>
|
|||
|
<span class="nl">background-position</span><span class="p">:</span> <span class="nb">center</span> <span class="m">100%</span><span class="p">;</span>
|
|||
|
<span class="nl">background-size</span><span class="p">:</span> <span class="n">contain</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="nc">.user-container</span><span class="nd">:before</span> <span class="p">{</span>
|
|||
|
<span class="nl">content</span><span class="p">:</span> <span class="sx">url("../../img/yannick-white64x64.png")</span><span class="p">;</span>
|
|||
|
<span class="nl">background</span><span class="p">:</span> <span class="m">#0000</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier le fichier <code class="language-plaintext highlighter-rouge">/usr/share/ssowat/portal/assets/themes/yann/custom_overlay.css</code></p>
|
|||
|
|
|||
|
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">#ynh-overlay-switch</span> <span class="p">{</span>
|
|||
|
<span class="c">/* FIXME : idk if this is an issue or not to have /yunohost/sso hard-coded here */</span>
|
|||
|
<span class="nl">background-image</span><span class="p">:</span> <span class="sx">url("/yunohost/sso/assets/img/ym-70x70.png")</span><span class="p">;</span>
|
|||
|
<span class="nl">right</span><span class="p">:</span> <span class="m">60px</span><span class="p">;</span>
|
|||
|
<span class="nl">border-color</span><span class="p">:</span> <span class="m">#7EA93D</span><span class="p">;</span>
|
|||
|
<span class="nl">background-color</span><span class="p">:</span> <span class="m">#7EA93D</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Activer le thème <code class="language-plaintext highlighter-rouge">nano /etc/ssowat/conf.json.persistent</code></p>
|
|||
|
|
|||
|
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
|
|||
|
</span><span class="nl">"theme"</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="s2">"yann"</span><span class="p">,</span><span class="w">
|
|||
|
</span><span class="p">}</span><span class="w">
|
|||
|
</span></code></pre></div></div>
|
|||
|
|
|||
|
<p>!!! Rrafraîchir le cache du navigateur pour que le thème se propage complètement ( Ctrl+Maj+R sur Firefox)</p>
|
|||
|
|
|||
|
<p><img src="/images/cx21-yunohost-theme-yann.png" alt="" width="600" /></p>
|
|||
|
|
|||
|
<h3 id="mise-à-jour">Mise à jour</h3>
|
|||
|
|
|||
|
<h4 id="system-et-app">system et app</h4>
|
|||
|
|
|||
|
<p>En mode su</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yunohost tools update
|
|||
|
# si mise à jour possible
|
|||
|
yunohost tools upgrade apps
|
|||
|
yunohost tools upgrade system
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>AIDE</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>YunoHost update
|
|||
|
|
|||
|
positional arguments:
|
|||
|
TARGET What to update, "apps" (application catalog) or "system" (fetch
|
|||
|
available package upgrades, equivalent to apt update), "all" for
|
|||
|
both
|
|||
|
|
|||
|
optional arguments:
|
|||
|
-h, --help show this help message and exit
|
|||
|
--apps (Deprecated, see first positional arg) Fetch the application
|
|||
|
list to check which apps can be upgraded
|
|||
|
--system (Deprecated, see first positional arg) Fetch available system
|
|||
|
packages upgrades (equivalent to apt update)
|
|||
|
root@yanfi:/home/admin# yunohost tools upgrade -h
|
|||
|
usage: yunohost tools upgrade [{apps,system}] [-h] [--apps] [--system]
|
|||
|
|
|||
|
YunoHost upgrade
|
|||
|
|
|||
|
positional arguments:
|
|||
|
{apps,system} What to upgrade, either "apps" (all apps) or "system" (all
|
|||
|
system packages)
|
|||
|
|
|||
|
optional arguments:
|
|||
|
-h, --help show this help message and exit
|
|||
|
--apps (Deprecated, see first positional arg) Upgrade all
|
|||
|
applications
|
|||
|
--system (Deprecated, see first positional arg) Upgrade only the
|
|||
|
system packages
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<h4 id="navidrome">Navidrome</h4>
|
|||
|
|
|||
|
<p><strong>Mise à jour Navidrome avec une version compilée (langue FR par défaut)</strong></p>
|
|||
|
|
|||
|
<p>Mise à jour (version compilée avec langue française par défaut et transmise par filezilla)</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl stop navidrome.service
|
|||
|
sudo cp ~/navidrome /opt/yunohost/navidrome/navidrome
|
|||
|
sudo chown -R navidrome:navidrome /opt/yunohost/navidrome
|
|||
|
sudo chmod +x /opt/yunohost/navidrome
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Relance et vérification</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl restart navidrome
|
|||
|
sudo yunohost service log navidrome
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p><strong>NE PAS FAIRE MAJ Navidrome</strong><br />
|
|||
|
<em>Il faut renseigner le fichier manifest.json avec la version update pour ne pas faire la mise à jour !!!</em><br />
|
|||
|
EXEMPLE : <code class="language-plaintext highlighter-rouge">yunohost tools update</code></p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[...]
|
|||
|
apps:
|
|||
|
0:
|
|||
|
current_version: 0.42.1~ynh1
|
|||
|
id: navidrome
|
|||
|
label: Zic Navidrome zic.cinay.eu
|
|||
|
new_version: 0.42.1~ynh2
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
<p>Modifier la version dans le fichier manifest.json de l’application Navidrome</p>
|
|||
|
|
|||
|
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sed -i 's/0.42.1~ynh1/0.42.1~ynh2/g' /etc/yunohost/apps/navidrome/manifest.json
|
|||
|
</code></pre></div></div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2020-11-22T00: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="/2020/11/19/VNC-controle-bureau-distance-via-Tunnel-SSH.html">VNC - x11vnc prise de contrôle bureau à distance</a></div><div class="next"><span>SUIVANT</span><a href="/2020/11/25/NEW-PC1-ArchLinux-XFCE-ASUS-H110M-A.html">PC1 Ordinateur Bureau ArchLinux xfce (NEW)</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>
|
|||
|
|