yannstatic/static/2021/09/14/HostMyServers-VPS-server85393-Debian-Buster-HDD-250Go.html

3071 lines
244 KiB
HTML
Raw Permalink Normal View History

2024-10-31 20:18:37 +01:00
<!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>HostMyServers, server85393 Debian 10 (HDD 250Go) - hms.xoyaz.xyz - YannStatic</title>
<meta name="description" content="https://www.hostmyservers.fr/Accès client">
<link rel="canonical" href="https://static.rnmkcy.eu/2021/09/14/HostMyServers-VPS-server85393-Debian-Buster-HDD-250Go.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}&nbsp;{title}</a></li>'
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{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;">HostMyServers, server85393 Debian 10 (HDD 250Go) - hms.xoyaz.xyz</h1></header></div><meta itemprop="headline" content="HostMyServers, server85393 Debian 10 (HDD 250Go) - hms.xoyaz.xyz"><div class="article__info clearfix"><ul class="left-col menu"><li>
2024-11-08 14:10:33 +01:00
<a class="button button--secondary button--pill button--sm" style="color:#00FFFF" href="/archive.html?tag=vps">vps</a>
2024-10-31 20:18:37 +01:00
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">14&nbsp;sept.&nbsp;2021</span>
<span title="Modification" style="color:#00FF7F">15&nbsp;nov.&nbsp;&nbsp;2021</span></li></ul></div><meta itemprop="datePublished" content="2021-11-15T00:00:00+01:00">
<meta itemprop="keywords" content="vps"><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">&#8679;</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><img src="/images/hms.png" alt="" width="80" /><br />
<a href="https://www.hostmyservers.fr/">https://www.hostmyservers.fr/</a><br />
<a href="https://www.hostmyservers.fr/user">Accès client</a></p>
<h2 id="kvm-debian-buster">KVM Debian Buster</h2>
<p><img src="/images/debian-buster-logo1.png" alt=" " width="100" /></p>
<p>Virtualization Type (KVM)<br />
CPU 2<br />
Memory 4 GB<br />
Disk Space 250 Go<br />
Operating System Debian 10 Buster (64-bit)<br />
IPv4 Address 45.145.166.51<br />
IPv6 Address 2a04:ecc0:8:a8:4567:833:0:1</p>
<h3 id="connexion-root">Connexion root</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh root@45.145.166.51
</code></pre></div></div>
<p>Changement mot de passe</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>passwd root
</code></pre></div></div>
<p>Mise à jour</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update &amp;&amp; apt upgrade
</code></pre></div></div>
<p>Installer utilitaires</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install rsync curl tmux jq figlet git mailutils dnsutils p7zip-full -y
</code></pre></div></div>
<h3 id="hostname">Hostname</h3>
<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: server85393
Icon name: computer-vm
Chassis: vm
Machine ID: a7f055c469ef4bb3be932070c99c7cd7
Boot ID: 57351a6ba7824484993707cafec46eea
Virtualization: kvm
Operating System: Debian GNU/Linux 10 (buster)
Kernel: Linux 4.19.0-12-cloud-amd64
Architecture: x86-64
</code></pre></div></div>
<h3 id="adresse-ipv4-ipv6">Adresse IPV4 IPV6</h3>
<p>Le paramétrage réseau par défaut</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/network/interfaces.d/50-cloud-init
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># This file is generated from information provided by the datasource. Changes
# to it will not persist across an instance reboot. To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
auto lo
iface lo inet loopback
dns-nameservers 8.8.8.8
auto eth0
iface eth0 inet static
address 45.145.166.51/24
gateway 45.145.166.1
# control-alias eth0
iface eth0 inet6 static
address 2a04:ecc0:8:a8:4567:0833::1/64
gateway 2a04:ecc0:8:a8::1
</code></pre></div></div>
<h3 id="création-utilisateur">Création utilisateur</h3>
<p>Utilisateur <strong>userhms</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>useradd -m -d /home/userhms/ -s /bin/bash userhms
</code></pre></div></div>
<p>Mot de passe <strong>userhms</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>passwd userhms
</code></pre></div></div>
<p>Visudo pour les accès root via utilisateur <strong>userhms</strong></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt <span class="nb">install sudo
echo</span> <span class="s2">"userhms ALL=(ALL) NOPASSWD: ALL"</span> <span class="o">&gt;&gt;</span> /etc/sudoers
</code></pre></div></div>
<p>Déconnexion puis connexion ssh en mode utilisateur</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh userhms@45.145.166.51
</code></pre></div></div>
<h3 id="openssh-clé-et-script">OpenSSH, clé et script</h3>
<p><img src="/images/ssh_logo1.png" alt="OpenSSH" width="70" /><br />
<strong>connexion avec clé</strong><br />
<u>sur l'ordinateur de bureau</u>
Générer une paire de clé curve25519-sha256 (ECDH avec Curve25519 et SHA2) pour une liaison SSH avec le serveur.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh-keygen -t ed25519 -o -a 100 -f ~/.ssh/hms-sto-250
</code></pre></div></div>
<p>Envoyer les clés publiques sur le serveur KVM</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh-copy-id -i ~/.ssh/hms-sto-250.pub userhms@45.145.166.51
</code></pre></div></div>
<p><u>sur le serveur KVM</u>
On se connecte</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh userhms@45.145.166.51
</code></pre></div></div>
<p>Modifier la configuration serveur SSH</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/ssh/sshd_config
</code></pre></div></div>
<p>Modifier</p>
<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Port</span> = <span class="m">55051</span>
<span class="n">PermitRootLogin</span> <span class="n">no</span>
<span class="n">PasswordAuthentication</span> <span class="n">no</span>
</code></pre></div></div>
<p><u>session SSH ne se termine pas correctement lors d'un "reboot" à distance</u><br />
Si vous tentez de <strong>redémarrer/éteindre</strong> une machine distance par <strong>ssh</strong>, vous pourriez constater que votre session ne se termine pas correctement, vous laissant avec un terminal inactif jusquà lexpiration dun long délai dinactivité. Il existe un bogue 751636 à ce sujet. Pour linstant, la solution de contournement à ce problème est dinstaller :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt-get install libpam-systemd
</code></pre></div></div>
<p>cela terminera la session ssh avant que le réseau ne tombe.<br />
Veuillez noter quil est nécessaire que PAM soit activé dans sshd.</p>
<p>Relancer openSSH</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl restart sshd
</code></pre></div></div>
<p>Accès depuis le poste distant avec la clé privée</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh userhms@45.145.166.51 -p 55051 -i ~/.ssh/hms-sto-250
</code></pre></div></div>
<h3 id="fail2ban">Fail2Ban</h3>
<p><em>Fail2ban est un framework de prévention contre les intrusions dont le but est de bloquer les adresses IP inconnues qui tentent de pénétrer dans votre système. Ce logiciel est recommandé, même essentiel, pour se prémunir contre toute attaque brutale contre vos services.</em></p>
<p>Pour installer le package logiciel, utilisez la commande suivante :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install fail2ban
</code></pre></div></div>
<p>Une fois le paquet installé, il faut modifier le fichier de configuration de ce dernier pour ladapter à votre usage. Avant toute modification, il est recommandé deffectuer une sauvegarde du fichier de configuration en tapant la commande suivante :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.conf.backup
</code></pre></div></div>
<p>Apportez ensuite vos modifications sur le fichier :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/fail2ban/jail.conf
</code></pre></div></div>
<p>Une fois ces modifications terminées, redémarrez le service à laide de la commande suivante :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl restart fail2ban
</code></pre></div></div>
<p>Pour toute demande complémentaire concernant Fail2Ban, nhésitez pas à consulter la <a href="https://www.fail2ban.org/wiki/index.php/Main_Page">documentation officielle de cet outil</a></p>
<h3 id="outils-scripts-motd-et-ssh_rc_bash">Outils, scripts motd et ssh_rc_bash</h3>
<p>Motd</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm /etc/motd &amp;&amp; sudo nano /etc/motd
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ___ ____ _____ ___ _____
___ ___ _ __ __ __ ___ _ __ ( _ )| ___||___ / / _ \|___ /
/ __| / _ \| '__|\ \ / // _ \| '__|/ _ \|___ \ |_ \| (_) | |_ \
\__ \| __/| | \ V /| __/| | | (_) |___) |___) |\__, |___) |
|___/_\___||_| \_/ \___||_| \___/|____/|____/ /_/|____/
|_____| ____ _ _ _ ____ _ __ __ ____ _
| || | | ___| / || || | | ___| / | / /_ / /_ | ___| / |
| || |_|___ \ | || || |_|___ \ | || '_ \ | '_ \ |___ \ | |
|__ _|___) |_ | ||__ _|___) |_ | || (_) || (_) |_ ___) || |
|_| |____/(_)|_| |_| |____/(_)|_| \___/ \___/(_)|____/ |_|
</code></pre></div></div>
<p>Script <strong>ssh_rc_bash</strong></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/server85393.png" alt="" /></p>
<h3 id="parefeu-ufw">Parefeu UFW</h3>
<p><img src="/images/ufw-logo1.png" alt="ufw" width="50" /></p>
<p><em>UFW, ou pare - feu simple , est une interface pour gérer les règles de pare-feu dans Arch Linux, Debian ou Ubuntu. UFW est utilisé via la ligne de commande (bien quil dispose dinterfaces graphiques disponibles), et vise à rendre la configuration du pare-feu facile.</em></p>
<p>Installation <strong>Debian / Ubuntu</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt-get install ufw
</code></pre></div></div>
<p><em>Par défaut, les jeux de règles dUFW sont vides, de sorte quil napplique aucune règle de pare-feu, même lorsque le démon est en cours dexécution.</em></p>
<p>Les règles</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo ufw allow 55051/tcp # port SSH
sudo ufw allow http # port 80
sudo ufw allow https # port 443
sudo ufw allow DNS # port 53
</code></pre></div></div>
<p>Activer le parefeu</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo ufw enable
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
</code></pre></div></div>
<p>Status</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> sudo ufw status verbose
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
DNS ALLOW Anywhere
55051/tcp ALLOW Anywhere
80/tcp (v6) ALLOW Anywhere (v6)
443/tcp (v6) ALLOW Anywhere (v6)
DNS (v6) ALLOW Anywhere (v6)
55051/tcp (v6) ALLOW Anywhere (v6)
</code></pre></div></div>
<h3 id="domaine-hmsxoyazxyz-cloud-ebook-et-zic">Domaine hms.xoyaz.xyz (cloud ebook et zic)</h3>
<p><img src="/images/dns-logo.png" alt="dns" width="50" /><br />
OVH configuration domaine xoyaz.xyz</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$TTL 3600
@ IN SOA dns106.ovh.net. tech.ovh.net. (2021111506 86400 3600 3600000 300)
IN NS ns106.ovh.net.
IN NS dns106.ovh.net.
cloud IN A 45.145.166.51
cloud IN AAAA 2a04:ecc0:8:a8:4567:0833::1
ebook IN A 45.145.166.51
ebook IN AAAA 2a04:ecc0:8:a8:4567:0833::1
hms IN A 45.145.166.51
hms IN AAAA 2a04:ecc0:8:a8:4567:0833::1
zic IN A 45.145.166.51
zic IN AAAA 2a04:ecc0:8:a8:4567:0833::1
</code></pre></div></div>
<h2 id="certificats-lets-encrypt">Certificats Lets Encrypt</h2>
<p><img src="/images/letsencrypt-logo1.png" alt="letsencrypt" width="80" /></p>
<p>Installation gestionnaire des certificats Lets Encrypt</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ~
sudo apt install socat # prérequis
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install
</code></pre></div></div>
<p>Les clés OVH API <br />
Génération des certificats</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>acme.sh --dns dns_ovh --server letsencrypt --issue --keylength ec-384 -d 'hms.xoyaz.xyz' -d 'cloud.xoyaz.xyz' -d 'ebook.xoyaz.xyz' -d 'zic.xoyaz.xyz'
</code></pre></div></div>
<p>Résultat de linstallation</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Thu 30 Sep 2021 12:43:31 PM CEST] Your cert is in: /home/userhms//.acme.sh/hms.xoyaz.xyz_ecc/hms.xoyaz.xyz.cer
[Thu 30 Sep 2021 12:43:31 PM CEST] Your cert key is in: /home/userhms//.acme.sh/hms.xoyaz.xyz_ecc/hms.xoyaz.xyz.key
[Thu 30 Sep 2021 12:43:31 PM CEST] The intermediate CA cert is in: /home/userhms//.acme.sh/hms.xoyaz.xyz_ecc/ca.cer
[Thu 30 Sep 2021 12:43:31 PM CEST] And the full chain certs is there: /home/userhms//.acme.sh/hms.xoyaz.xyz_ecc/fullchain.cer
</code></pre></div></div>
<p>Installation des certificats</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mkdir -p /etc/ssl/private/
sudo chown $USER -R /etc/ssl/private/
acme.sh --ecc --install-cert -d 'xoyaz.xyz' -d '*.xoyaz.xyz' --key-file /etc/ssl/private/xoyaz.xyz-key.pem --fullchain-file /etc/ssl/private/xoyaz.xyz-fullchain.pem --reloadcmd 'sudo systemctl reload nginx.service'
</code></pre></div></div>
<p class="warning">Supprimer ` reloadcmd sudo systemctl reload nginx.service` à la ligne précédente si Nginx nest pas installé</p>
<p>Editer le crontab</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>crontab -e
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>56 0 * * * "/home/userhms/.acme.sh"/acme.sh --cron --home "/home/userhms/.acme.sh" --renew-hook "/home/userhms/.acme.sh/acme.sh --ecc --install-cert -d 'xoyaz.xyz' -d '*.xoyaz.xyz' --key-file /etc/ssl/private/xoyaz.xyz-key.pem --fullchain-file /etc/ssl/private/xoyaz.xyz-fullchain.pem --reloadcmd 'sudo systemctl reload nginx.service'" &gt; /dev/null
</code></pre></div></div>
<p class="warning">Nginx est installé</p>
<h2 id="hmsxoyazxyz">hms.xoyaz.xyz</h2>
<h3 id="nginx-light">Nginx Light</h3>
<p><img src="/images/nginx-logo.png" alt="" width="50" /></p>
<p>Installation</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install nginx-light
</code></pre></div></div>
<p>create: 2020-06-29
modifier le fichier <code class="language-plaintext highlighter-rouge">/etc/nginx/nginx.conf</code></p>
<p>On autorise tls1.2 et tls1.3 uniquement et ciphers off</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[...]
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
[...]
</code></pre></div></div>
<p>Accès dossier pour les fichiers de configuration</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[...]
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
# include /etc/nginx/sites-enabled/*;
[...]
</code></pre></div></div>
<h3 id="php8">PHP8</h3>
<p><img src="/images/php8-logo.png" alt="" width="50" /></p>
<p>Ajout du dépôt sury.org</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
</code></pre></div></div>
<p>Pour installer la version de 8 de php, ajouter le dépôt sury.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt <span class="nb">install</span> <span class="nt">-y</span> lsb-release apt-transport-https ca-certificates wget
wget <span class="nt">-O</span> /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
<span class="nb">echo</span> <span class="s2">"deb https://packages.sury.org/php/ </span><span class="si">$(</span>lsb_release <span class="nt">-sc</span><span class="si">)</span><span class="s2"> main"</span> |tee /etc/apt/sources.list.d/php.list
</code></pre></div></div>
<p>Installer php8.0</p>
<p>Mise à jour des dépôts :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt update
</code></pre></div></div>
<p>Installation de php8.0 et/ou php8.0-fpm
paquet php8.0 :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt install php8.0 php8.0-fpm php8.0-sqlite3 php8.0-gd
</code></pre></div></div>
<h3 id="hmsxoyazxyzconf">hms.xoyaz.xyz.conf</h3>
<p>Créer le fichier <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/hms.xoyaz.xyz.conf</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
listen 80;
listen [::]:80;
server_name hms.xoyaz.xyz;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name hms.xoyaz.xyz;
ssl_certificate /etc/ssl/private/xoyaz.xyz-fullchain.pem;
ssl_certificate_key /etc/ssl/private/xoyaz.xyz-key.pem;
root /var/www/html;
index index.html index.php;
# TLS 1.3 only
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/ssl/private/xoyaz.xyz-fullchain.pem;
# fichiers de configuration
include /etc/nginx/conf.d/hms.xoyaz.xyz.d/*.conf;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
}
# replace with the IP address of your resolver
resolver 8.8.8.8;
}
</code></pre></div></div>
<p>Créer le sous-dossier</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mkdir /etc/nginx/conf.d/hms.xoyaz.xyz.d/
</code></pre></div></div>
<p>Vérifier</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nginx -t
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
</code></pre></div></div>
<p>Recharger nginx</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl reload nginx
</code></pre></div></div>
<p>Pour tester le php</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "&lt;?php phpinfo(); ?&gt;" | sudo tee /var/www/html/info.php
</code></pre></div></div>
<p>https://hms.xoyaz.xyz/info.php</p>
<h3 id="page-daccueil">Page daccueil</h3>
<p>Déposer une image dans le dossier <code class="language-plaintext highlighter-rouge">/var/www/html</code><br />
Créer un fichier <code class="language-plaintext highlighter-rouge">/var/www/html/index.html</code></p>
<pre><code class="language-hmtl">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;title&gt;hms.xoyaz.xyz&lt;/title&gt;
&lt;style type="text/css" media="screen" &gt;
html {
margin:0;
padding:0;
background: url(wallpaper.jpg) no-repeat center fixed;
-webkit-background-size: cover; /* pour anciens Chrome et Safari */
background-size: cover; /* version standardisée */
}
body { color: white; }
a:link {
color: grey;
background-color: transparent;
text-decoration: none;
}
a {
text-decoration: underline;
background-color: transparent;
color: #a00;
}
a:visited {
color: #844;
}
a:hover, a:focus, a:active {
text-decoration: none;
color: white;
background: #800;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Serveur hms.xoyaz.xyz&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Lien <a href="https://hms.xoyaz.xyz">https://hms.xoyaz.xyz</a><br />
<img src="/images/hms.xoyaz.xyz-accueil.png" alt="" width="500" /></p>
<h2 id="rsync-sshfs-sauvegardes">Rsync SSHFS Sauvegardes</h2>
<h3 id="synchro-rsync">Synchro rsync</h3>
<p><img src="/images/rsync.png" alt="" width="50" /></p>
<p>Synchronisation entre xoyaz.xyz et hms.xoyaz.xyz <br />
Commande à exécuter sur hms.xoyaz.xyz</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rsync -avz --progress --stats --human-readable --rsync-path="sudo rsync" -e "ssh -p 55036 -i /home/userhms/.ssh/OVZ-STORAGE-128 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" usernl@xoyaz.xyz:/home/usernl/backup/* /home/userhms/sshfs/
</code></pre></div></div>
<h3 id="dossier-accessible-via-sshfs">Dossier accessible via sshfs</h3>
<p><img src="/images/sshfs-logo.png" alt="" width="50" /></p>
<p><em>On va créer des dossiers qui seront accessibles via le réseau pour les clients SSHFS</em></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir ~/sshfs
mkdir ~/sshfs/yanfi.space
</code></pre></div></div>
<p>NOTE: Pour que les clients accèdent au dossier , il faut leur fournir une clé privé SSH</p>
<p><strong>Opérations Coté client (yanfi.space)</strong><br />
Le but, créer un accès réseau sur un autre serveur pour les gros volumes de fichiers (musique, livres, etc…) <br />
Créer dossier local <strong>/opt/hms-sshfs/</strong> : <code class="language-plaintext highlighter-rouge">sudo mkdir -p /opt/hms-sshfs</code>
Créer une liaison réseau sécurisée SSHFS entre le client et le serveur : <code class="language-plaintext highlighter-rouge">sudo apt install sshfs</code> <br />
Autorisations : <code class="language-plaintext highlighter-rouge">sudo -s; echo "user_allow_other" &gt;&gt; /etc/fuse.conf </code></p>
<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/hms-sshfs -C -p 55051 -oIdentityFile=/home/admin/.ssh/hms-sto-250
</code></pre></div></div>
<blockquote>
<p>NOTE: Il faut mettre ladresse 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/hms-sshfs</code> , déconnexion <code class="language-plaintext highlighter-rouge">fusermount -u /opt/hms-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/hms-sshfs fuse.sshfs _netdev,identityfile=/home/admin/.ssh/hms-sto-250,allow_other,port=55051 0 0
</code></pre></div></div>
<h3 id="sauvegardes">Sauvegardes</h3>
<p><img src="/images/sauvegarde_logo.png" alt="" width="50" /></p>
<p><strong>Opérations réalisées sur yanfi.space</strong></p>
<p>Sauvegarde complète de yunohost yanfi.space sur le serveur hms.xoyaz.xyz via sshfs</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">* -&gt; 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">* -&gt; 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* -&gt; 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 &gt; /dev/null
</code></pre></div></div>
<h2 id="authentification-double-facteur">Authentification double facteur</h2>
<p><img src="/images/2fa-logo.png" alt="" width="50" /></p>
<p><em>Authentification double facteur (2FA) PHP TOTP</em><br />
<a href="/2021/03/17/PHP_Authentification_2FA(Arno0x).html">PHP - Portail dauthentification web authentification à deux facteurs (2FA).</a></p>
<p><strong>TwoFactorAuth</strong> utilise PHP et des bibliothèques</p>
<ul>
<li>php 8.0 pour nginx</li>
<li>La bibliothèque GD</li>
<li>La bibliothèque SQLite3</li>
</ul>
<p>Installation</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install php8.0-fpm php8.0-gd php8.0-sqlite3
git clone https://gitea.cinay.eu/yann/twofactorauth.git
sudo mv twofactorauth /var/www/html/
sudo chown www-data.www-data -R /var/www/html/twofactorauth
</code></pre></div></div>
<p>Modifier QRCODE_TITLE,SESSION_NAME et AUTH_SUCCEED_REDIRECT_URL dans le fichier de configuration <code class="language-plaintext highlighter-rouge">/var/www/html/twofactorauth/config.php</code></p>
<p>Ouvrir le lien https://hms.xoyaz.xyz/twofactorauth/index.php</p>
<p>Créer ladministrateur “xoyaz”, son mot de passe et scanner le Qr Code avec une application TOTP <br />
<img src="/images/2faxoyaz1.png" alt="" width="400" /><br />
Scanner le Qr Code avec une application TOTP<br />
<img src="/images/2faxoyaz2.png" alt="" width="400" /><br />
Administration : https://hms.xoyaz.xyz/twofactorauth/admin/admin.php</p>
<h2 id="applications-web">Applications Web</h2>
<h3 id="python">Python</h3>
<p><strong><a href="/2021/09/23/Debian-Python-3.html">Debian Python version 3 par défaut</a></strong><br />
Installer Pip Python 3</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt update
sudo apt install python3-venv python3-pip
</code></pre></div></div>
<p>Les versions</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>userhms@server85393:~$ python --version
Python 3.7.3
userhms@server85393:~$ pip --version
pip 18.1 from /usr/lib/python3/dist-packages/pip (python 3.7)
</code></pre></div></div>
<h3 id="calibre-ebookxoyazxyz">Calibre ebook.xoyaz.xyz</h3>
<p>Python et Pip version 3 sont installés<br />
Les outils</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install sqlite3 python3-setuptools imagemagick
pip install wheel
</code></pre></div></div>
<p>Installation</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd $HOME
git clone https://github.com/janeczku/calibre-web.git
cd calibre-web
# installation des prérequis
pip install --system --target vendor -r requirements.txt
cd ..
# déplacer vers /var/www
sudo mv calibre-web /var/www/
# les droits
sudo chown $USER.www-data -R /var/www/calibre-web/
</code></pre></div></div>
<p>Service systemd calibre-web pour le lancement automatique</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nano /etc/systemd/system/calibre-web.service
</code></pre></div></div>
<p>Contenu du fichier</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Unit]
Description=Service calibre-web
After=network.target
[Service]
Type=simple
User=userhms
ExecStart=/usr/bin/python /var/www/calibre-web/cps.py
[Install]
WantedBy=multi-user.target
</code></pre></div></div>
<blockquote>
<p><strong>ATTENTION!</strong> , <strong>User</strong> est lutilisateur connecté ($USER)</p>
</blockquote>
<p>Lancer le service calibre-web :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl start calibre-web
</code></pre></div></div>
<p>Vérifier:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl status calibre-web
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>● calibre-web.service - Service calibre-web
Loaded: loaded (/etc/systemd/system/calibre-web.service; disabled; vendor preset: enabled)
Active: active (running) since Fri 2021-09-24 17:55:28 CEST; 7s ago
Main PID: 19781 (python)
Tasks: 2 (limit: 4718)
Memory: 63.7M
CGroup: /system.slice/calibre-web.service
└─19781 /usr/bin/python /var/www/calibre-web/cps.py
Sep 24 17:55:28 server85393 systemd[1]: Started Service calibre-web.
</code></pre></div></div>
<p>Activation</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable calibre-web
</code></pre></div></div>
<p>Le domaine “ebook.xoyaz.xyz” est activé avec les certificats lets encrypt</p>
<p>Le fichier de configuration nginx <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/ebook.xoyaz.xyz.conf</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
listen 80;
listen [::]:80;
server_name ebook.xoyaz.xyz;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ebook.xoyaz.xyz;
ssl_certificate /etc/ssl/private/xoyaz.xyz-fullchain.pem;
ssl_certificate_key /etc/ssl/private/xoyaz.xyz-key.pem;
root /var/www/html;
index index.html index.php;
# TLS 1.3 only
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/ssl/private/xoyaz.xyz-fullchain.pem;
# replace with the IP address of your resolver
resolver 8.8.8.8;
location / {
proxy_pass http://127.0.0.1:8083;
}
}
</code></pre></div></div>
<p>Vérifier<br />
<code class="language-plaintext highlighter-rouge">sudo nginx -t</code><br />
Redémarrer nginx<br />
<code class="language-plaintext highlighter-rouge">sudo systemctl reload nginx</code></p>
<p>accès à la configuration <a href="https://ebook.xoyaz.xyz/config">https://ebook.xoyaz.xyz/config</a><br />
<img src="/images/calibre-web16.png" alt="" width="500" /></p>
<p><img src="/images/calibre-web1.png" alt="" height="300" /></p>
<p>puis cliquer sur <strong>Connexion</strong><br />
Par défaut: <em>Nom dutilisateur:</em> admin , <em>Mot de passe:</em> admin123</p>
<p>Paramétrage , cliquer sur <strong>Admin</strong> (pas sur admin avec le a minuscule)</p>
<p>Cliquer sur <strong>Add new user</strong><br />
Username : yannick<br />
Email address : yannick@yanfi.net<br />
Password : xxxxxx<br />
Kindle email:<br />
Language : français<br />
Show books with language : Show all<br />
Admin avec tous les droits<br />
<img src="/images/calibre-web17.png" alt="" width="400" /><br />
Et cliquer sur <strong>Save</strong></p>
<p>Se reconnecter avec lutilisateur <em>yannick</em><br />
Cliquer sur <em>Administration</em> et sélectionner <em>admin</em> , cocher la case “Supprimer cet utilisateur”<br />
Il reste lutilisateur/administrateur <strong>yannick</strong></p>
<p>Paramétrage<br />
Configuration de linterface utilisateur → Configuration du mode daffichage : Thème sombre</p>
<p>Réglages par défaut pour les nouveaux utilisateurs
Mode de visualisation par défaut pour les nouveaux utilisateurs</p>
<h3 id="transmission">Transmission</h3>
<p><img src="/images/icon_transmission.png" alt="" width="50" /></p>
<p><em>Transmission permet le téléchargement et la création de torrents. Ce logiciel supporte les technologies décentralisées sans tracker, tel que PEX, DHT et les liens magnets.</em></p>
<p>Pour linstallation suivre ce lien :<a href="/2020/11/07/debian-transmission-daemon.html">Debian Transmission</a></p>
<p>Ajout utilisateur courant au groupe “debian-transmission”</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo usermod -a -G debian-transmission $USER
</code></pre></div></div>
<p><strong>Accès sécurisé sur le site hms.xoyaz.xyz/transmission avec login mot de passe et 2FA</strong></p>
<p>On supprime le fichier de configuration <code class="language-plaintext highlighter-rouge">~/.config/transmission-daemon/settings.json</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm ~/.config/transmission-daemon/settings.json
</code></pre></div></div>
<p>Modification du fichier de configuration <code class="language-plaintext highlighter-rouge">/etc/transmission-daemon/settings.json</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl stop transmission-daemon.service
</code></pre></div></div>
<p>Le fichier de configuration “transmission”</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">"alt-speed-down"</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="p">,</span><span class="w">
</span><span class="nl">"alt-speed-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"alt-speed-time-begin"</span><span class="p">:</span><span class="w"> </span><span class="mi">540</span><span class="p">,</span><span class="w">
</span><span class="nl">"alt-speed-time-day"</span><span class="p">:</span><span class="w"> </span><span class="mi">127</span><span class="p">,</span><span class="w">
</span><span class="nl">"alt-speed-time-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"alt-speed-time-end"</span><span class="p">:</span><span class="w"> </span><span class="mi">1020</span><span class="p">,</span><span class="w">
</span><span class="nl">"alt-speed-up"</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="p">,</span><span class="w">
</span><span class="nl">"bind-address-ipv4"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0.0.0.0"</span><span class="p">,</span><span class="w">
</span><span class="nl">"bind-address-ipv6"</span><span class="p">:</span><span class="w"> </span><span class="s2">"::"</span><span class="p">,</span><span class="w">
</span><span class="nl">"blocklist-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"blocklist-url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://www.example.com/blocklist"</span><span class="p">,</span><span class="w">
</span><span class="nl">"cache-size-mb"</span><span class="p">:</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w">
</span><span class="nl">"dht-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="nl">"download-dir"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/home/userhms/torrent/complet"</span><span class="p">,</span><span class="w">
</span><span class="nl">"download-limit"</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="p">,</span><span class="w">
</span><span class="nl">"download-limit-enabled"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
</span><span class="nl">"download-queue-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="nl">"download-queue-size"</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w">
</span><span class="nl">"encryption"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w">
</span><span class="nl">"idle-seeding-limit"</span><span class="p">:</span><span class="w"> </span><span class="mi">30</span><span class="p">,</span><span class="w">
</span><span class="nl">"idle-seeding-limit-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"incomplete-dir"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/home/userhms/torrent/encours"</span><span class="p">,</span><span class="w">
</span><span class="nl">"incomplete-dir-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"lpd-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"max-peers-global"</span><span class="p">:</span><span class="w"> </span><span class="mi">200</span><span class="p">,</span><span class="w">
</span><span class="nl">"message-level"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w">
</span><span class="nl">"peer-congestion-algorithm"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
</span><span class="nl">"peer-id-ttl-hours"</span><span class="p">:</span><span class="w"> </span><span class="mi">6</span><span class="p">,</span><span class="w">
</span><span class="nl">"peer-limit-global"</span><span class="p">:</span><span class="w"> </span><span class="mi">200</span><span class="p">,</span><span class="w">
</span><span class="nl">"peer-limit-per-torrent"</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="p">,</span><span class="w">
</span><span class="nl">"peer-port"</span><span class="p">:</span><span class="w"> </span><span class="mi">51413</span><span class="p">,</span><span class="w">
</span><span class="nl">"peer-port-random-high"</span><span class="p">:</span><span class="w"> </span><span class="mi">65535</span><span class="p">,</span><span class="w">
</span><span class="nl">"peer-port-random-low"</span><span class="p">:</span><span class="w"> </span><span class="mi">49152</span><span class="p">,</span><span class="w">
</span><span class="nl">"peer-port-random-on-start"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"peer-socket-tos"</span><span class="p">:</span><span class="w"> </span><span class="s2">"default"</span><span class="p">,</span><span class="w">
</span><span class="nl">"pex-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="nl">"port-forwarding-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"preallocation"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w">
</span><span class="nl">"prefetch-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="nl">"queue-stalled-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="nl">"queue-stalled-minutes"</span><span class="p">:</span><span class="w"> </span><span class="mi">30</span><span class="p">,</span><span class="w">
</span><span class="nl">"ratio-limit"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w">
</span><span class="nl">"ratio-limit-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"rename-partial-files"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-authentication-required"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-bind-address"</span><span class="p">:</span><span class="w"> </span><span class="s2">"0.0.0.0"</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-host-whitelist"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-host-whitelist-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-password"</span><span class="p">:</span><span class="w"> </span><span class="s2">"{2f217a20225338209def1c9fa5587751c6a608d8Onz8WkP5"</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-port"</span><span class="p">:</span><span class="w"> </span><span class="mi">9091</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/transmission/"</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-username"</span><span class="p">:</span><span class="w"> </span><span class="s2">"yan"</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-whitelist"</span><span class="p">:</span><span class="w"> </span><span class="s2">"127.0.0.1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"rpc-whitelist-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"scrape-paused-torrents-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="nl">"script-torrent-done-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"script-torrent-done-filename"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
</span><span class="nl">"seed-queue-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"seed-queue-size"</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w">
</span><span class="nl">"speed-limit-down"</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="p">,</span><span class="w">
</span><span class="nl">"speed-limit-down-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"speed-limit-up"</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="p">,</span><span class="w">
</span><span class="nl">"speed-limit-up-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"start-added-torrents"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
</span><span class="nl">"trash-original-torrent-files"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"umask"</span><span class="p">:</span><span class="w"> </span><span class="mi">7</span><span class="p">,</span><span class="w">
</span><span class="nl">"upload-limit"</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="p">,</span><span class="w">
</span><span class="nl">"upload-limit-enabled"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
</span><span class="nl">"upload-slots-per-torrent"</span><span class="p">:</span><span class="w"> </span><span class="mi">14</span><span class="p">,</span><span class="w">
</span><span class="nl">"utp-enabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>Création des dossiers et des droits</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p ~/torrent/{complet,encours}
</code></pre></div></div>
<p>Modifier le groupe du dossier completed (remplacer www-data par debian-transmission)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo chown debian-transmission.debian-transmission -R ~/torrent
</code></pre></div></div>
<p>Ajoutez le nom dutilisateur au groupe debian-transmission :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo usermod -a -G debian-transmission $USER
</code></pre></div></div>
<p>Relancer transmission</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl start transmission-daemon
</code></pre></div></div>
<p>Le fichier de configuration <strong>/etc/nginx/conf.d/hms.xoyaz.xyz.conf</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
listen 80;
listen [::]:80;
server_name hms.xoyaz.xyz;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name hms.xoyaz.xyz;
ssl_certificate /etc/ssl/private/xoyaz.xyz-fullchain.pem;
ssl_certificate_key /etc/ssl/private/xoyaz.xyz-key.pem;
root /var/www/html;
index index.html index.php;
# TLS 1.3 only
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/ssl/private/xoyaz.xyz-fullchain.pem;
# fichiers de configuration
include /etc/nginx/conf.d/hms.xoyaz.xyz.d/*.conf;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
}
# replace with the IP address of your resolver
resolver 8.8.8.8;
location = /twofactorauth/login/login.php {
allow all;
auth_request off;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.0-fpm.sock; # PHP8.0
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location = /twofactorauth/nginx/auth.php {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.0-fpm.sock; # PHP8.0
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param CONTENT_LENGTH "";
}
location /twofactorauth/ {
index index.php;
}
location /twofactorauth/db/ {
deny all;
}
location /transmission {
proxy_pass http://127.0.0.1:9091;
auth_request /twofactorauth/nginx/auth.php;
error_page 401 =401 $scheme://$host/twofactorauth/login/login.php?from=$uri;
proxy_buffering off;
}
}
</code></pre></div></div>
<p>recharger nginx</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo nginx -t
sudo systemctl reload nginx
</code></pre></div></div>
<p>Lien <a href="https://hms.xoyaz.xyz/transmission">https://hms.xoyaz.xyz/transmission</a><br />
<img src="/images/cx11b-debian-3.png" alt="" width="500" /><br />
saisir utilisateur, mot de passe et le jeton OTP correspondant</p>
<p><img src="/images/cx11b-debian-2.png" alt="" width="500" /></p>
<p>Pour avoir le lien sur la page daccueil, ajouter ce qui suite avant la balise <code class="language-plaintext highlighter-rouge">&lt;/body&gt;</code> du fichier <code class="language-plaintext highlighter-rouge">/var/www/html/index.html</code></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;p&gt;&lt;a</span> <span class="na">href=</span><span class="s">"/transmission"</span><span class="nt">&gt;</span>Transmission<span class="nt">&lt;/a&gt;</span>
<span class="nt">&lt;em&gt;</span> permet le téléchargement et la création de torrents.<span class="nt">&lt;br&gt;</span>Ce logiciel supporte les technologies décentralisées sans tracker, tel que PEX, DHT et les liens magnets.<span class="nt">&lt;/em&gt;</span>
<span class="nt">&lt;/p&gt;</span>
</code></pre></div></div>
<h3 id="nextcloud">Nextcloud</h3>
<p><img src="/images/nextcloud_logo_128px.png" alt="" /><br />
<a href="/2021/09/18/Nextcloud22_Nginx_PHP8-FPM_MariaDB_SSL-TLS.html">Nextcloud 22 Nginx, PHP8.0, MariaDB et SSL/TLS cloud.xoyaz.xyz</a></p>
<p>Lien https://cloud.xoyaz.xyz</p>
<p><a href="/2021/09/18/Nextcloud22_Nginx_PHP8-FPM_MariaDB_SSL-TLS.html#authentification-%C3%A0-deux-facteurs">Authentification à deux facteurs</a><br />
<img src="/images/cloud_xoyaz_xyz03.png" alt="" width="600" /></p>
<p>Un thème sombre basé sur <strong>Breeze Dark</strong> <br />
<img src="/images/cloud_xoyaz_xyz01.png" alt="" width="500" /><br />
<img src="/images/cloud_xoyaz_xyz02.png" alt="" width="600" /></p>
<p>Messagerie<br />
<img src="/images/cloud_xoyaz_xyz04.png" alt="" width="500" /><br />
Lancer le test<br />
<img src="/images/cloud_xoyaz_xyz05.png" alt="" width="500" /></p>
<p>Stockage externe (paramétrage en admin)<br />
<img src="/images/cloud_xoyaz_xyz09.png" alt="" width="600" /></p>
<p>Applications</p>
<ul>
<li>Notes</li>
</ul>
<h3 id="netdata-non-installe">NetData (NON INSTALLE)</h3>
<p><a href="https://github.com/netdata/netdata">https://github.com/netdata/netdata</a></p>
<h4 id="installation">Installation</h4>
<p>Pour installer Netdata à partir des sources sur la plupart des systèmes Linux (physiques, virtuels, conteneurs, IoT, périphérie), exécutez notre script dinstallation en une ligne. Ce script télécharge et construit toutes les dépendances, y compris celles requises pour se connecter à Netdata Cloud si vous le souhaitez, et active les mises à jour nocturnes automatiques et les statistiques anonymes.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
bash &lt;(curl -Ss https://my-netdata.io/kickstart.sh)
</code></pre></div></div>
<p>Patienter …</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> --- We are done! ---
^
|.-. .-. .-. .-. .-. . netdata .-. .-
| '-' '-' '-' '-' '-' is installed and running now! -' '-'
+----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---&gt;
enjoy real-time performance and health monitoring...
OK
</code></pre></div></div>
<p>Pour afficher le tableau de bord Netdata<br />
Ouvrir un terminal sur le client linux qui dispose des clés ssh et lancer la commande</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh -L 9000:localhost:19999 userhms@45.145.166.51 -p 55051 -i /home/yann/.ssh/hms-sto-250
</code></pre></div></div>
<p>Ouvrir un navigateur sur le même client et saisir localhost:9000
<img src="/images/netdata_xoyaz_xyz01.png" alt="" width="600" /></p>
<h4 id="désinstallation">Désinstallation</h4>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
wget https://raw.githubusercontent.com/netdata/netdata/master/packaging/installer/netdata-uninstaller.sh
chmod +x ./netdata-uninstaller.sh
./netdata-uninstaller.sh --yes --env /etc/netdata/.environment
</code></pre></div></div>
<h3 id="audio-navidrome">Audio Navidrome</h3>
<p><a href="https://www.navidrome.org/docs/installation/linux/">Steps to install on Ubuntu Linux (and other Debian based distros)</a></p>
<p>Les étapes suivantes ont été testées sur Ubuntu 18.04 et devraient fonctionner sur toutes les versions 16.04 et supérieures ainsi que sur les autres distros basées sur Debian. Tout au long de ces instructions, les commandes auront des espaces réservés pour lutilisateur (<code class="language-plaintext highlighter-rouge">&lt;user&gt;</code>) et le groupe (<code class="language-plaintext highlighter-rouge">&lt;group&gt;</code>) sous lesquels vous souhaitez exécuter Navidrome et le chemin du dossier de musique (<code class="language-plaintext highlighter-rouge">&lt;library_path&gt;</code>). Si vous utilisez une médiathèque existante, assurez-vous que lutilisateur a les droits sur la médiathèque.</p>
<p><strong>Conditions préalables à la mise à jour et à linstallation</strong><br />
Assurez-vous que votre système est à jour et installez ffmpeg.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt update &amp;&amp; sudo apt upgrade
sudo apt install ffmpeg
</code></pre></div></div>
<p>Par défaut, la commande useradd ne crée pas de répertoires de base, mais pour un démon, je vous recommande dutiliser loption système et de remplacer le shell par un shell inexistant afin que personne ne puisse se connecter à ce compte (sous ssh par exemple):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo useradd -r -s /bin/false navidrome
</code></pre></div></div>
<p><strong>Créer une structure de répertoire</strong><br />
Créez un répertoire pour stocker lexécutable Navidrome et un répertoire de travail avec les permissions appropriées.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo install -d -o navidrome -g navidrome /opt/navidrome
sudo install -d -o navidrome -g navidrome /var/lib/navidrome
</code></pre></div></div>
<p><strong>Obtenir Navidrome</strong><br />
Téléchargez la dernière version depuis la <a href="https://github.com/navidrome/navidrome/releases">page des versions</a>, extrayez le contenu dans le répertoire exécutable et définissez les autorisations pour les fichiers. (Remplacez lURL ci-dessous par celle de la page des versions) :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wget https://github.com/navidrome/navidrome/releases/download/v0.45.1/navidrome_0.45.1_Linux_arm64.tar.gz -O Navidrome.tar.gz
sudo tar -xvzf Navidrome.tar.gz -C /opt/navidrome/
sudo chown -R navidrome:navidrome /opt/navidrome
</code></pre></div></div>
<p><strong>Créer le fichier de configuration</strong></p>
<p>Dans le répertoire de travail, <code class="language-plaintext highlighter-rouge">/var/lib/navidrome</code> créer un nouveau fichier nommé <code class="language-plaintext highlighter-rouge">navidrome.toml</code> avec les paramètres suivants.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MusicFolder = "/home/userhms/sshfs/musique"
</code></pre></div></div>
<p>Pour dautres options de configuration, voir la page des <a href="https://www.navidrome.org/docs/usage/configuration-options/">options de configuration</a>.</p>
<p><strong>Créer une unité Systemd</strong><br />
Créez un nouveau fichier sous <code class="language-plaintext highlighter-rouge">/etc/systemd/system/</code> nommé <code class="language-plaintext highlighter-rouge">navidrome.service</code> avec les données suivantes.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/etc/systemd/system/navidrome.service
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Unit]
Description=Navidrome Music Server and Streamer compatible with Subsonic/Airsonic
After=remote-fs.target network.target
AssertPathExists=/var/lib/navidrome
[Install]
WantedBy=multi-user.target
[Service]
User=navidrome
Group=navidrome
Type=simple
ExecStart=/opt/navidrome/navidrome --configfile "/var/lib/navidrome/navidrome.toml"
WorkingDirectory=/var/lib/navidrome
TimeoutStopSec=20
KillMode=process
Restart=on-failure
# See https://www.freedesktop.org/software/systemd/man/systemd.exec.html
DevicePolicy=closed
NoNewPrivileges=yes
PrivateTmp=yes
PrivateUsers=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictNamespaces=yes
RestrictRealtime=yes
SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap
ReadWritePaths=/var/lib/navidrome
# You can uncomment the following line if you're not using the jukebox This
# will prevent navidrome from accessing any real (physical) devices
#PrivateDevices=yes
# You can change the following line to `strict` instead of `full` if you don't
# want navidrome to be able to write anything on your filesystem outside of
# /var/lib/navidrome.
ProtectSystem=full
# You can uncomment the following line if you don't have any media in /home/*.
# This will prevent navidrome from ever reading/writing anything there.
#ProtectHome=true
# You can customize some Navidrome config options by setting environment variables here. Ex:
#Environment=ND_BASEURL="/navidrome"
</code></pre></div></div>
<p><strong>Démarrez le service Navidrome</strong><br />
Rechargez le démon de service, démarrez le service nouvellement créé, et vérifiez quil a démarré correctement.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl daemon-reload
sudo systemctl start navidrome.service
sudo systemctl status navidrome.service
</code></pre></div></div>
<p>Si le service a démarré correctement, vérifiez que vous pouvez accéder à http://localhost:4533.<br />
Ouvrir un terminal sur le client linux qui dispose des clés ssh et lancer la commande</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh -L 9500:localhost:4533 userhms@45.145.166.51 -p 55051 -i /home/yann/.ssh/hms-sto-250
</code></pre></div></div>
<p>Ouvrir un navigateur sur le client et saisir <a href="URL">localhost:9500</a> pour afficher le serveur audio<br />
<img src="/images/zic_xoyaz_xyz.png" alt="" width="400" /></p>
<p>Démarrez Navidrome au démarrage</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable navidrome.service
</code></pre></div></div>
<p><strong>Proxy nginx zic.xoyaz.xyz</strong><br />
Le domaine “zic.xoyaz.xyz” est activé avec les certificats lets encrypt</p>
<p>Le fichier de configuration nginx <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/zic.xoyaz.xyz.conf</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
listen 80;
listen [::]:80;
server_name zic.xoyaz.xyz;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name zic.xoyaz.xyz;
ssl_certificate /etc/ssl/private/xoyaz.xyz-fullchain.pem;
ssl_certificate_key /etc/ssl/private/xoyaz.xyz-key.pem;
root /var/www/html;
index index.html index.php;
# TLS 1.3 only
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/ssl/private/xoyaz.xyz-fullchain.pem;
# replace with the IP address of your resolver
resolver 1.1.1.1;
location / {
proxy_pass http://127.0.0.1:4533;
}
}
</code></pre></div></div>
<h3 id="serveur-de-messagerie">Serveur de messagerie</h3>
<ul>
<li><a href="https://www.bennetrichter.de/en/tutorials/mailcow-dockerized/">Mailcow</a></li>
<li><a href="https://www.julienmousqueton.fr/mailcow-installer-un-serveur-mail-en-moins-de-10-minutes/">Mailcow : installer un serveur mail en moins de 10 minutes</a></li>
</ul>
<p><strong>Préparations</strong></p>
<p>Avant de commencer linstallation de Mailcow, vous devez effectuer quelques préparatifs, qui concernent principalement les paramètres DNS du domaine que vous souhaitez utiliser pour recevoir et envoyer des e-mails. Pour ce faire, suivez les étapes ci-dessous :</p>
<ol>
<li>Le nom dhôte de votre serveur doit être “mail”, donc le FQDN doit être “mail.xoyaz.xyz”.</li>
<li>Ajoutez un enregistrement A pour le sous-domaine “mail” (mail.xoyaz.xyz) et faites en sorte quil pointe vers ladresse IP du serveur de messagerie.</li>
<li>Ajoutez un enregistrement MX pour votre domaine et faites en sorte quil pointe vers le sous-domaine “mail” que vous venez de créer (mail.xoyaz.xyz) avec une priorité de 10.</li>
<li>Définissez un enregistrement CNAME pour les sous-domaines “autodiscover” et “autoconfig” et définissez la destination des deux enregistrements CNAME sur le sous-domaine de messagerie (mail.xoyaz.xyz).</li>
<li>Ajoutez un enregistrement TXT pour votre domaine et définissez la valeur de “v=spf1 mx ~all”, pour permettre au serveur spécifié dans lenregistrement MX (le serveur de messagerie où Mailcow sera installé) denvoyer des e-mails avec votre domaine comme domaine expéditeur. Le “~all” signifie que les autres serveurs ne sont pas autorisés à envoyer des e-mails à partir de votre domaine, mais ces e-mails seront tout de même livrés (softfail).</li>
<li>Définissez un enregistrement PTR (Reverse DNS) pour ladresse IP de votre serveur et définissez la valeur du FQDN de votre serveur (“mail.xoyaz.xyz”). Vous pouvez définir cet enregistrement PTR directement dans linterface web de tout bon hébergeur comme Contabo. Pour certains fournisseurs, vous devez écrire un e-mail ou ouvrir un ticket de support.</li>
</ol>
<p>Ajouter à la configuration dns ovh domaine xoyaz.xyz</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> IN MX 10 mail.xoyaz.xyz.
IN TXT "v=spf1 mx ~all"
autoconfig IN CNAME mail.xoyaz.xyz.
autodiscover IN CNAME mail.xoyaz.xyz.
mail IN A 45.145.166.51
</code></pre></div></div>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2021-09-14T00:00:00+02: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>
&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2021/08/24/tmux.html">Tmux , multiplexeur de terminaux</a></div><div class="next"><span>SUIVANT</span><a href="/2021/09/18/Nextcloud22_Nginx_PHP8-FPM_MariaDB_SSL-TLS.html">Nginx, PHP8.0, MariaDB et Nextcloud</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}&nbsp;{title}</a>&nbsp;(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>