yannstatic/static/2022/07/21/HostMyServers-VPS-server32771-Debian-Bullseye.html

3246 lines
256 KiB
HTML
Raw 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, server32771 Debian 11 (Bullseye) - YannStatic</title>
<meta name="description" content="Accès client">
<link rel="canonical" href="https://static.rnmkcy.eu/2022/07/21/HostMyServers-VPS-server32771-Debian-Bullseye.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, server32771 Debian 11 (Bullseye)</h1></header></div><meta itemprop="headline" content="HostMyServers, server32771 Debian 11 (Bullseye)"><div class="article__info clearfix"><ul class="left-col menu"><li>
<a class="button button--secondary button--pill button--sm"
href="/archive.html?tag=vps">vps</a>
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">21&nbsp;juil.&nbsp;2022</span>
<span title="Modification" style="color:#00FF7F">&nbsp;9&nbsp;nov.&nbsp;&nbsp;2022</span></li></ul></div><meta itemprop="datePublished" content="2022-11-09T00: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/user">Accès client</a></p>
<ul>
<li><a href="#debian-bullseye">Debian bullseye</a>
<ul>
<li><a href="#reconfigurer-locales">Reconfigurer locales</a></li>
<li><a href="#ntp-avec-systemd-timesyncd">NTP avec systemd-timesyncd</a></li>
<li><a href="#dns-resolvconf">DNS resolvconf</a></li>
<li><a href="#création-utilisateur">Création utilisateur</a></li>
<li><a href="#openssh-clé-et-script">OpenSSH, clé et script</a></li>
<li><a href="#outils-scripts-motd-et-ssh_rc_bash">Outils, scripts motd et ssh_rc_bash</a></li>
<li><a href="#parefeu-ufw">Parefeu UFW</a></li>
<li><a href="#nginx-compilé">Nginx compilé</a></li>
<li><a href="#domaine-et-certificats">Domaine et certificats</a>
<ul>
<li><a href="#ovh-domaine-ouestyanfr">OVH domaine ouestyan.fr</a></li>
<li><a href="#certificats-lets-encrypt">Certificats Lets Encrypt</a></li>
</ul>
</li>
<li><a href="#nginx-securityconfinc">Nginx security.conf.inc</a></li>
<li><a href="#fail2ban">Fail2ban</a></li>
<li><a href="#notifications">Notifications</a></li>
<li><a href="#docker">Docker</a></li>
</ul>
</li>
<li><a href="#sauvegardes">Sauvegardes</a>
<ul>
<li><a href="#données-srvdatayan">Données /srv/datayan</a></li>
<li><a href="#borgbackup">BorgBackup</a></li>
</ul>
</li>
<li><a href="#ouestyanfr">ouestyan.fr</a>
<ul>
<li><a href="#accueil">Accueil</a></li>
<li><a href="#navidrome">Navidrome</a></li>
<li><a href="#searx">Searx</a>
<ul>
<li><a href="#installation-des-paquets-prérequis">Installation des paquets prérequis</a></li>
<li><a href="#installer-searx-et-les-dépendances">Installer searx et les dépendances</a></li>
<li><a href="#configuration">Configuration</a></li>
<li><a href="#vérifier-en-local">Vérifier en local</a></li>
<li><a href="#uwsgi">uwsgi</a></li>
<li><a href="#nginx-proxy-searx">nginx proxy searx</a></li>
</ul>
</li>
<li><a href="#nextcloud">Nextcloud</a>
<ul>
<li><a href="#transmission-torrent">Transmission Torrent</a></li>
<li><a href="#installer-transmission-daemon">Installer transmission-daemon</a></li>
<li><a href="#proxy-nginx">Proxy nginx</a></li>
<li><a href="#dossiers-et-configuration">Dossiers et configuration</a></li>
<li><a href="#transmissionouestyanfr">transmission.ouestyan.fr</a></li>
</ul>
</li>
<li><a href="#test-de-sécurité">Test de sécurité</a></li>
</ul>
</li>
</ul>
<h2 id="debian-bullseye">Debian bullseye</h2>
<p><img src="/images/debian11-logo.png" alt="" height="60" /></p>
<p>PARAMETRES DACCES:<br />
Ladresse IPv4 du VPS est : 45.145.166.178<br />
Ladresse IPv6 du VPS est : 2a04:ecc0:8:a8:4567:4989::1</p>
<p>Connexion SSH en “root”</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh root@45.145.166.178
</code></pre></div></div>
<p>Modifier le fichier des dépôts <code class="language-plaintext highlighter-rouge">/etc/apt/sources.list</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>deb http://deb.debian.org/debian bullseye main contrib non-free
deb-src http://deb.debian.org/debian bullseye main contrib non-free
#deb http://deb.debian.org/debian bullseye-updates main contrib non-free
#deb-src http://deb.debian.org/debian bullseye-updates main contrib non-free
deb http://security.debian.org/debian-security bullseye-security main
deb-src http://security.debian.org/debian-security bullseye-security main
</code></pre></div></div>
<p>Rafraîchir</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>Créer mot de passe “root”</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>passwd
</code></pre></div></div>
<p>Le paramétrage réseau par défaut <code class="language-plaintext highlighter-rouge">/etc/network/interfaces.d/50-cloud-init</code><br />
Il faut commenter la ligne <code class="language-plaintext highlighter-rouge">dns-nameservers 194.9.173.89 2a04:ecc0:4::89</code> pour utiliser dnsmasq</p>
<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 194.9.173.89 2a04:ecc0:4::89
auto eth0
iface eth0 inet static
address 45.145.166.178/24
gateway 45.145.166.1
# control-alias eth0
iface eth0 inet6 static
address 2a04:ecc0:8:a8:4567:4989::1/64
gateway 2a04:ecc0:8:a8::1
</code></pre></div></div>
<h3 id="reconfigurer-locales">Reconfigurer locales</h3>
<p>installer le paquet locales-all</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt-get install locales-all
</code></pre></div></div>
<h3 id="ntp-avec-systemd-timesyncd">NTP avec systemd-timesyncd</h3>
<p>Le service ntp de systemd sappelle <strong>systemd-timesyncd.service</strong><br />
La configuration se fait dans <code class="language-plaintext highlighter-rouge">/etc/systemd/timesyncd.conf</code></p>
<blockquote>
<p>Si vous utilisez un autre service pour gérer NTP, assurez-vous de le(s) désactiver : ntpd chronyd</p>
</blockquote>
<p>Installation</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install systemd-timesyncd
</code></pre></div></div>
<p>Par défaut</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl status systemd-timesyncd.service
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>● systemd-timesyncd.service - Network Time Synchronization
Loaded: loaded (/lib/systemd/system/systemd-timesyncd.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2022-09-25 02:50:09 UTC; 10h ago
Docs: man:systemd-timesyncd.service(8)
Main PID: 10822 (systemd-timesyn)
Status: "Initial synchronization to time server 188.68.41.203:123 (0.debian.pool.ntp.org)."
Tasks: 2 (limit: 4698)
Memory: 1012.0K
CPU: 54ms
CGroup: /system.slice/systemd-timesyncd.service
└─10822 /lib/systemd/systemd-timesyncd
</code></pre></div></div>
<p>Fuseau Europe/Paris</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo timedatectl set-timezone Europe/Paris
</code></pre></div></div>
<p>Horloge système synchronisée</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>timedatectl
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Local time: dim. 2022-09-25 15:47:44 CEST
Universal time: dim. 2022-09-25 13:47:44 UTC
RTC time: dim. 2022-09-25 13:47:45
Time zone: Europe/Paris (CEST, +0200)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
</code></pre></div></div>
<h3 id="dnsmasq">dnsmasq</h3>
<p><img src="/images/Dnsmasq_logo.png" alt="" /><br />
<a href="/2019/12/25/DNSmasq.html">DNSmasq (installation et configuration)</a></p>
<p>Installation</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install dnsmasq
</code></pre></div></div>
<p>Si le paquet <strong>resolvconf</strong> est installé, dnsmasq utilisera sa sortie plutôt que le contenu de <code class="language-plaintext highlighter-rouge">/etc/resolv.conf</code> pour trouver les serveurs de noms en amont. Décommenter la ligne <code class="language-plaintext highlighter-rouge">#IGNORE_RESOLVCONF=yes</code> empêche ce comportement.<br />
Notez que linclusion dune ligne <code class="language-plaintext highlighter-rouge">resolv-file=&lt;filename&gt;</code> dans <code class="language-plaintext highlighter-rouge">/etc/dnsmasq.conf</code> nest pas suffisante pour remplacer <strong>resolvconf</strong> si celui-ci est installé : la ligne <code class="language-plaintext highlighter-rouge">#IGNORE_RESOLVCONF=yes</code> doit être décommentée.</p>
<p><code class="language-plaintext highlighter-rouge">/etc/default/dnsmasq</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Whether or not to run the dnsmasq daemon; set to 0 to disable.
# Note that this is only valid when using SYSV init. For systemd,
# use "systemctl disable dnsmasq"
ENABLED=1
# By default search this drop directory for configuration options.
# Libvirt leaves a file here to make the system dnsmasq play nice.
# Comment out this line if you don't want this. The dpkg-* are file
# endings which cause dnsmasq to skip that file. This avoids pulling
# in backups made by dpkg.
CONFIG_DIR=/etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new
# If the resolvconf package is installed, dnsmasq will use its output
# rather than the contents of /etc/resolv.conf to find upstream
# nameservers. Uncommenting this line inhibits this behaviour.
# Note that including a "resolv-file=&lt;filename&gt;" line in
# /etc/dnsmasq.conf is not enough to override resolvconf if it is
# installed: the line below must be uncommented.
IGNORE_RESOLVCONF=yes
</code></pre></div></div>
<p>Configuration de dnsmasq avec le fichier /etc/resolv.conf</p>
<p>Vous devez faire en sorte que toutes les requêtes soient envoyées à dnsmasq en ajoutant les adresses localhost comme seuls serveurs de noms dans le fichier <code class="language-plaintext highlighter-rouge">/etc/resolv.conf</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
# 127.0.0.53 is the systemd-resolved stub resolver.
# run "resolvectl status" to see details about the actual nameservers.
nameserver 127.0.0.1
</code></pre></div></div>
<p>Ouvrir le fichier <code class="language-plaintext highlighter-rouge">/etc/dnsmasq.conf</code> et effectuer les réglages de configuration</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>domain-needed
expand-hosts
localise-queries
interface=lo
resolv-file=/etc/resolv.dnsmasq.conf
</code></pre></div></div>
<p>Explications</p>
<ul>
<li><strong>domain-needed</strong> : Ne transmet pas les requêtes ne contenant pas un nom de domaine complet. Par exemple,une requête pour machine ne sera pas transmise aux serveurs DNS de votre FAI, alors quune requête pour machine.domain.com le sera.</li>
<li>Si vous souhaitez quun domaine soit automatiquement ajouté aux noms simples dans un fichier hosts, décommentez loption <strong>expand-hosts</strong></li>
<li><strong>localise-queries</strong> : Retourne des réponses aux requêtes DNS dépendantes de linterface sur laquelle la requête a été reçue, à partir du fichier /etc/hosts. Si un nom dans /etc/hosts a plus dune adresse associée avec lui, et quune des adresses au moins est dans le même sous-réseau que linterface sur laquelle la requête a été reçue, alors ne retourne que la(les) adresse(s) du sous-réseau considéré. Cela permet davoir dans /etc/hosts un serveur avec de multiples adresses, une pour chacune de ses interfaces, et de fournir aux hôtes ladresse correcte (basée sur le réseau auquel ils sont attachés). Cette possibilité est actuellement limitée à IPv4.</li>
</ul>
<p>Pour lutter contre la censure sur Internet, <a href="https://www.fdn.fr/actions/dns/">FDN</a> fait le choix de mettre à disposition de toutes et tous des résolveurs DNS récursifs ouverts.<br />
Le fichier des dns <code class="language-plaintext highlighter-rouge">/etc/resolv.dnsmasq.conf</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nameserver 80.67.169.12
nameserver 2001:910:800::12
nameserver 80.67.169.40
nameserver 2001:910:800::40
</code></pre></div></div>
<p>Redémarrer dnsmasq</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl restart dnsmasq
</code></pre></div></div>
<p>Vérifications, installer dnsutils au préalable (<code class="language-plaintext highlighter-rouge">sudo apt install dnsutils</code>)</p>
<h3 id="création-utilisateur">Création utilisateur</h3>
<p>Utilisateur <strong>hmsuser</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>useradd -m -d /home/hmsuser/ -s /bin/bash hmsuser
</code></pre></div></div>
<p>Mot de passe <strong>hmsuser</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>passwd hmsuser
</code></pre></div></div>
<p>Visudo pour les accès root via utilisateur <strong>hmsuser</strong></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="s2">"hmsuser 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 hmsuser@45.145.166.178
</code></pre></div></div>
<h3 id="openssh-clé-et-script">OpenSSH, clé et script</h3>
<p><img src="/images/ssh_logo1.png" alt="OpenSSH" height="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/server32771
</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/server32771.pub hmsuser@45.145.166.178
</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 hmsuser@45.145.166.178
</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">55178</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>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 hmsuser@45.145.166.178 -p 55178 -i ~/.ssh/server32771
</code></pre></div></div>
<h3 id="outils-scripts-motd-et-ssh_rc_bash">Outils, scripts motd et ssh_rc_bash</h3>
<p><img src="/images/bash-shell-logo.png" alt="" height="50" /><br />
Installer utilitaires</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install rsync curl tmux jq figlet git
</code></pre></div></div>
<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> _ _ _ __ __ ___
| || | ___ ___| |_ | \/ | _ _ / __| ___ _ _ __ __ ___ _ _ ___
| __ |/ _ \(_-&lt;| _|| |\/| || || |\__ \/ -_)| '_|\ V // -_)| '_|(_-&lt;
|_||_|\___//__/ \__||_| |_| \_, ||___/\___||_| \_/ \___||_| /__/
|__/____ ___ ____ ____ _
___ ___ _ _ __ __ ___ _ _|__ /|_ )|__ ||__ |/ |
(_-&lt;/ -_)| '_|\ V // -_)| '_||_ \ / / / / / / | |
/__/\___||_| \_/ \___||_| |___//___| /_/ /_/ |_|
_ __
___ _ _ ___ ___| |_ _ _ __ _ _ _ / _| _ _
/ _ \| || |/ -_)(_-&lt;| _|| || |/ _` || ' \ _ | _|| '_|
\___/ \_,_|\___|/__/ \__| \_, |\__,_||_||_|(_)|_| |_|
|__/
</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/hms.ouestyan.fr.png" alt="" /></p>
<h3 id="parefeu-ufw">Parefeu UFW</h3>
<p><img src="/images/ufw-logo.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 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-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>ufw allow 55178/tcp <span class="c"># port SSH</span>
<span class="nb">sudo </span>ufw allow http <span class="c"># port 80</span>
<span class="nb">sudo </span>ufw allow https <span class="c"># port 443</span>
<span class="nb">sudo </span>ufw allow DNS <span class="c"># port 53</span>
</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
-- ------ ----
55178/tcp ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
443 ALLOW IN Anywhere
53 (DNS) ALLOW IN Anywhere
55178/tcp (v6) ALLOW IN Anywhere (v6)
80/tcp (v6) ALLOW IN Anywhere (v6)
443 (v6) ALLOW IN Anywhere (v6)
53 (DNS (v6)) ALLOW IN Anywhere (v6)
</code></pre></div></div>
<h3 id="nginx-compilé">Nginx compilé</h3>
<p><img src="/images/nginx-logo.png" alt="" /></p>
<p>Utilisateur avec droits sudo</p>
<p>Télécharger le bash</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wget https://static.xoyaz.xyz/files/compilation-nginx-tls1.3.sh
chmod +x compilation-nginx-tls1.3.sh # rendre le bash exécutable
./compilation-nginx-tls1.3.sh # exécution
</code></pre></div></div>
<p>A la fin de la compilation</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Versions Nginx OpenSSL
nginx version: nginx/1.20.2
OpenSSL 1.1.1n 15 Mar 2022
</code></pre></div></div>
<h3 id="domaine-et-certificats">Domaine et certificats</h3>
<p>Se connecter sur HMS pour configurer le reverse dns <br />
45.145.166.178 &gt; ouestyan.fr<br />
Demander par ticket la modification du reverse dns ipv6<br />
2a04:ecc0:8:a8:4567:4989:0:1 &gt; ouestyan.fr</p>
<p>Changer le hostname</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo hostnamectl set-hostname ouestyan.fr
hostnamectl
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Static hostname: ouestyan.fr
Icon name: computer-vm
Chassis: vm
Machine ID: 0e0cc9839fc64a049ba55e3248fab176
Boot ID: f3913f931a8b4090a7d40ac500e2db0f
Virtualization: kvm
Operating System: Debian GNU/Linux 11 (bullseye)
Kernel: Linux 5.10.0-18-cloud-amd64
Architecture: x86-64
</code></pre></div></div>
<h4 id="ovh-domaine-ouestyanfr">OVH domaine ouestyan.fr</h4>
<p><img src="/images/dns-logo.png" alt="dns" width="50" /><br />
OVH configuration domaine <strong>ouestyan.fr</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$TTL 3600
@ IN SOA dns17.ovh.net. tech.ovh.net. (2022092612 86400 3600 3600000 60)
IN NS ns17.ovh.net.
IN NS dns17.ovh.net.
IN MX 10 ouestyan.fr.
IN A 45.145.166.178
IN AAAA 2a04:ecc0:8:a8:4567:4989::1
IN CAA 128 issue "letsencrypt.org"
* IN A 45.145.166.178
* IN AAAA 2a04:ecc0:8:a8:4567:4989::1
</code></pre></div></div>
<h4 id="certificats-lets-encrypt">Certificats Lets Encrypt</h4>
<p><img src="/images/letsencrypt-logo1.png" alt="letsencrypt" height="80" /><br />
Installation gestionnaire des certificats Lets Encrypt</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ~
# socat est prérequis (installé par défaut)
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install
</code></pre></div></div>
<p>Se reconnecter</p>
<p>Exporter les clés OVH API</p>
<p>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 'ouestyan.fr' -d '*.ouestyan.fr'
</code></pre></div></div>
<p>Ouvrir le lien dauthentification et relancer la commande précédente après le message “OVH authentication Success !” et patienter…</p>
<p>Résultat de linstallation</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[lun. 26 sept. 2022 08:36:37 CEST] Your cert is in: /home/hmsuser//.acme.sh/ouestyan.fr_ecc/ouestyan.fr.cer
[lun. 26 sept. 2022 08:36:37 CEST] Your cert key is in: /home/hmsuser//.acme.sh/ouestyan.fr_ecc/ouestyan.fr.key
[lun. 26 sept. 2022 08:36:38 CEST] The intermediate CA cert is in: /home/hmsuser//.acme.sh/ouestyan.fr_ecc/ca.cer
[lun. 26 sept. 2022 08:36:38 CEST] And the full chain certs is there: /home/hmsuser//.acme.sh/ouestyan.fr_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 'ouestyan.fr' -d '*.ouestyan.fr' --key-file /etc/ssl/private/ouestyan.fr-key.pem --fullchain-file /etc/ssl/private/ouestyan.fr-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>13 0 * * * "/home/hmsuser/.acme.sh"/acme.sh --cron --home "/home/hmsuser/.acme.sh" --renew-hook "/home/hmsuser/.acme.sh/acme.sh --ecc --install-cert -d 'ouestyan.fr' -d '*.ouestyan.fr' --key-file /etc/ssl/private/ouestyan.fr-key.pem --fullchain-file /etc/ssl/private/ouestyan.fr-fullchain.pem --reloadcmd 'sudo systemctl reload nginx.service'" &gt; /dev/null
</code></pre></div></div>
<h3 id="nginx-securityconfinc">Nginx security.conf.inc</h3>
<p><a href="/2022/10/22/Nginx_headers_SSL_HSTS_OCSP.html">Nginx headers,SSL,HSTS,OCSP</a></p>
<p>Créer un fichier pour un regroupement <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/security.conf.inc</code> mode intermédiaire</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> # /etc/nginx/conf.d/security.conf.inc
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m; # about 200000 sessions
ssl_session_tickets off;
# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Pre-defined FFDHE group (RFC 7919)
# From https://ssl-config.mozilla.org/ffdhe2048.txt
# https://security.stackexchange.com/a/149818
ssl_dhparam /etc/ssl/private/ffdhe2048.pem;
# Follows the Web Security Directives from the Mozilla Dev Lab and the Mozilla Obervatory + Partners
# https://wiki.mozilla.org/Security/Guidelines/Web_Security
# https://observatory.mozilla.org/
more_set_headers "Content-Security-Policy : upgrade-insecure-requests";
more_set_headers "Referrer-Policy: same-origin;"
more_set_headers "X-Content-Type-Options : nosniff";
more_set_headers "X-XSS-Protection : 1; mode=block";
more_set_headers "X-Download-Options : noopen";
more_set_headers "X-Permitted-Cross-Domain-Policies : none";
more_set_headers "X-Frame-Options : SAMEORIGIN";
# Disable the disaster privacy thing that is FLoC
more_set_headers "Permissions-Policy : interest-cohort=()";
# Disable gzip to protect against BREACH
# Read https://trac.nginx.org/nginx/ticket/1720 (text/html cannot be disabled!)
gzip off;
# Certificats Let's Encrypt
ssl_certificate /etc/ssl/private/ouestyan.fr-fullchain.pem;
ssl_certificate_key /etc/ssl/private/ouestyan.fr-key.pem;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
more_set_headers "Strict-Transport-Security : max-age=63072000; includeSubDomains; preload";
# OCSP settings
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/private/ouestyan.fr-fullchain.pem;
resolver 1.1.1.1;
</code></pre></div></div>
<p>Dans tous les Vhosts, il faut ajouter linclusion du fichier : <code class="language-plaintext highlighter-rouge">include /etc/nginx/conf.d/security.conf.inc;</code></p>
<h3 id="fail2ban">Fail2ban</h3>
<p><a href="/2022/09/27/Debian_11_Fail2ban_UFW.html">Installer et configurer Fail2ban + UFW sur Debian 11</a></p>
<h3 id="notifications">Notifications</h3>
<p><code class="language-plaintext warning highlighter-rouge">Il faut demander l'ouverture du port 25 au fournisseur du VPS</code></p>
<p>Le serveur doit pouvoir expédier des messages de notification par messagerie</p>
<ol>
<li>Il faut ajouter le port TCP 25 au parefeu : <code class="language-plaintext highlighter-rouge">sudo ufw allow 25</code></li>
<li>Configurer DNS de votre fournisseur de domaine, ici OVH<br />
Ajouter enregistrement MX : <strong>IN MX 10 ouestyan.fr.</strong> (le point est obligatoire après fr)</li>
<li>Procédures dinstallation et paramétrage →
<a href="/2022/08/27/Debian_Postfix_serveur_SMTP_envoi_uniquement.html">Debian - Installer et configurer Postfix comme serveur SMTP denvoi uniquement</a></li>
</ol>
<p>Test envoi message</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "Test envoi via postfix smtp" | mail -s "serveur debian" root
</code></pre></div></div>
<h3 id="docker">Docker</h3>
<p><a href="/2020/03/10/Docker-Debian-Buster.html">Docker + Docker Compose sur Debian, installation et utilisation</a></p>
<ul>
<li><strong>Docker Engine</strong> ou <strong>Docker Daemon</strong> correspondant au processus qui fait tourner Docker sur le système, en charge de la génération et lexécution des containers</li>
<li><strong>Docker Registry</strong> est un emplacement de stockage pour héberger les images de containers Docker (il peut être public ou privé)</li>
<li><strong>Docker Image</strong> correspondant à un fichier qui contient la définition dun container Docker (dépendances, configuration, etc.)</li>
<li><strong>Docker Client</strong> correspondant à lutilitaire en ligne de commande qui va permettre de gérer les containers (commande “docker”)</li>
<li><strong>Docker Container</strong> correspondant aux containers en eux-mêmes, tout en sachant quune image peut permettre de créer plusieurs containers avec chacun un identifiant unique</li>
</ul>
<h2 id="sauvegardes">Sauvegardes</h2>
<h3 id="données-srvdatayan">Données /srv/datayan</h3>
<p class="info">Le dossier datayan va contenir tous les dossiers de données :<br />
<strong>BiblioCalibre CalibreTechnique media musique static www</strong><br />
Lutilisateur doit avoir un ID=1000</p>
<p><strong>Opérations sur le serveur HostMyServers server32771 (yanfi.space)</strong><br />
Dans linstallation de base debian 11, lutilisateur à un ID=1000</p>
<p>Ajouter cet utilisateur au groupe users</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo usermod -a -G users $USER
</code></pre></div></div>
<p>Vérifier : <code class="language-plaintext highlighter-rouge">id $USER</code> → uid=1000(hmsuser) gid=1000(hmsuser) groups=1000(hmsuser),100(users)</p>
<p>Créer le dossier</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mkdir -p /srv/datayan
</code></pre></div></div>
<p>Donner les droits</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo chown $USER:users -R /srv/datayan
</code></pre></div></div>
<h3 id="borgbackup">BorgBackup</h3>
<p><img src="/images/borg-logo.png" alt="" height="50" /><br />
Installer borg : <code class="language-plaintext highlighter-rouge">sudo apt install borg</code><br />
Créer un utilisateur borg et son répertoire “home” → <code class="language-plaintext highlighter-rouge">/srv/data/borg-backups</code> : <code class="language-plaintext highlighter-rouge">sudo useradd -d /srv/data -m -r -U borg</code></p>
<p>Les clés publiques des serveurs autorisés se trouvent dans le fichier <strong>authorized_keys</strong> de lutilisateur <strong>borg</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@ouestyan:/home/hmsuser# su - borg
$ pwd
/srv/data/borg-backups
$ cat .ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMs2JATwIa9fPOk0gfOgm4YNIT9ZKfWwpXDamzZ5dVsh root@ouestline.xyz
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPuVXP+pUjvedC/htJmKXamAotLESDCRqU0MOoD7vqCA root@422x.l.time4vps.cloud
</code></pre></div></div>
<h2 id="ouestyanfr">ouestyan.fr</h2>
<h3 id="accueil">Accueil</h3>
<p>Déposer une image <code class="language-plaintext highlighter-rouge">wallpaper.jpg</code> dans le dossier <code class="language-plaintext highlighter-rouge">/var/www/default-www</code></p>
<p>Créer un fichier <code class="language-plaintext highlighter-rouge">/var/www/default-www/index.html</code></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;!DOCTYPE html&gt;</span>
<span class="nt">&lt;html&gt;</span>
<span class="nt">&lt;head&gt;</span>
<span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">&gt;</span>
<span class="nt">&lt;title&gt;</span>ouestyan.fr<span class="nt">&lt;/title&gt;</span>
<span class="nt">&lt;style </span><span class="na">type=</span><span class="s">"text/css"</span> <span class="na">media=</span><span class="s">"screen"</span> <span class="nt">&gt;</span>
<span class="nt">html</span> <span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span><span class="m">0</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span><span class="m">0</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="sx">url(wallpaper.jpg)</span> <span class="nb">no-repeat</span> <span class="nb">center</span> <span class="nb">fixed</span><span class="p">;</span>
<span class="nl">-webkit-background-size</span><span class="p">:</span> <span class="n">cover</span><span class="p">;</span> <span class="c">/* pour anciens Chrome et Safari */</span>
<span class="nl">background-size</span><span class="p">:</span> <span class="n">cover</span><span class="p">;</span> <span class="c">/* version standardisée */</span>
<span class="p">}</span>
<span class="nt">body</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span> <span class="p">}</span>
<span class="nt">a</span><span class="nd">:link</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="n">grey</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="nb">transparent</span><span class="p">;</span>
<span class="nl">text-decoration</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">a</span> <span class="p">{</span>
<span class="nl">text-decoration</span><span class="p">:</span> <span class="nb">underline</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="nb">transparent</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#a00</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">a</span><span class="nd">:visited</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#844</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">a</span><span class="nd">:hover</span><span class="o">,</span> <span class="nt">a</span><span class="nd">:focus</span><span class="o">,</span> <span class="nt">a</span><span class="nd">:active</span> <span class="p">{</span>
<span class="nl">text-decoration</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="m">#800</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">&lt;/style&gt;</span>
<span class="nt">&lt;/head&gt;</span>
<span class="nt">&lt;body&gt;</span>
<span class="nt">&lt;h1&gt;</span>Serveur ouestyan.fr<span class="nt">&lt;/h1&gt;</span>
<span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</code></pre></div></div>
<p><strong>ouestyan.fr.conf</strong></p>
<p>Créer le fichier <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/ouestyan.fr.conf</code></p>
<div class="language-nginx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">server</span> <span class="p">{</span>
<span class="kn">listen</span> <span class="mi">80</span><span class="p">;</span>
<span class="kn">listen</span> <span class="s">[::]:80</span><span class="p">;</span>
<span class="kn">server_name</span> <span class="s">ouestyan.fr</span><span class="p">;</span>
<span class="kn">return</span> <span class="mi">301</span> <span class="s">https://</span><span class="nv">$host$request_uri</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1"># /etc/nginx/conf.d/ouestyan.fr.conf</span>
<span class="k">server</span> <span class="p">{</span>
<span class="kn">listen</span> <span class="mi">443</span> <span class="s">ssl</span> <span class="s">http2</span><span class="p">;</span>
<span class="kn">listen</span> <span class="s">[::]:443</span> <span class="s">ssl</span> <span class="s">http2</span><span class="p">;</span>
<span class="kn">server_name</span> <span class="s">ouestyan.fr</span><span class="p">;</span>
<span class="kn">root</span> <span class="n">/var/www/default-www</span><span class="p">;</span>
<span class="kn">index</span> <span class="s">index.html</span><span class="p">;</span>
<span class="kn">include</span> <span class="n">/etc/nginx/conf.d/security.conf.inc</span><span class="p">;</span>
<span class="c1">#include /etc/nginx/conf.d/ouestyan.fr.d/*.conf;</span>
<span class="kn">access_log</span> <span class="n">/var/log/nginx/ouestyan.fr-access.log</span><span class="p">;</span>
<span class="kn">error_log</span> <span class="n">/var/log/nginx/ouestyan.fr-error.log</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Lien <a href="https://ouestyan.fr">https://ouestyan.fr</a> <br />
<img src="/images/ouestyan.fr.png" alt="" width="500" /></p>
<h3 id="navidrome">Navidrome</h3>
<p><a href="/2022/04/02/Audio_Navidrome-installation_sur_debian.html">Audio Navidrome, installation sur debian</a></p>
<p><strong><u>Installation navidrome</u></strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Conditions préalables à la mise à jour et à linstallation
sudo apt update &amp;&amp; sudo apt upgrade
sudo apt install libtag1-dev ffmpeg
# Utilisateur “navidrome”
sudo useradd -r -s /bin/false navidrome
# Créez un répertoire pour stocker lexécutable Navidrome
# et un répertoire de travail avec les permissions appropriées
sudo install -d -o navidrome -g navidrome /opt/navidrome
sudo install -d -o navidrome -g navidrome /var/lib/navidrome
# On utilise la version compilée disponible sous ~/navidrome
sudo mv navidrome /opt/navidrome/
sudo chown -R navidrome:navidrome /opt/navidrome
sudo chmod +x /opt/navidrome/navidrome
</code></pre></div></div>
<p>Fichier de configuration <strong>navidrome.toml</strong> : <code class="language-plaintext highlighter-rouge">sudo nano /var/lib/navidrome/navidrome.toml</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MusicFolder = "/srv/datayan/musique"
ND_PLAYLISTSPATH = "Playlists"
</code></pre></div></div>
<p>unité Systemd <strong>navidrome.service</strong> : <code class="language-plaintext highlighter-rouge">sudo nano /etc/systemd/system/navidrome.service</code></p>
<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>lancer le service</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>systemctl daemon-reload
<span class="nb">sudo </span>systemctl start navidrome.service
<span class="nb">sudo </span>systemctl <span class="nb">enable </span>navidrome.service
</code></pre></div></div>
<p>Tester navidrome, exécuter la commande sur un poste local ayant accès via ssh au serveur distant</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh -L 9500:localhost:4533 hmsuser@45.145.166.178 -p 55178 -i /home/yann/.ssh/server32771
</code></pre></div></div>
<p>Ouvrir le lien <code class="language-plaintext highlighter-rouge">localhost:9500</code> dans un navigateur</p>
<p><strong><u>Proxy nginx zic.ouestyan.fr</u></strong></p>
<p>Le fichier de configuration nginx <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/zic.ouestyan.fr.conf</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
listen 80;
listen [::]:80;
server_name zic.ouestyan.fr;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name zic.ouestyan.fr;
include /etc/nginx/conf.d/security.conf.inc;
location / {
proxy_pass http://127.0.0.1:4533;
}
}
</code></pre></div></div>
<p>Valider et recharger ginx</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://zic.ouestyan.fr">https://zic.ouestyan.fr</a><br />
<img src="/images/zic.ouestyan.fr.png" alt="" width="500" /></p>
<h3 id="searx">Searx</h3>
<p><a href="https://searx.github.io/searx/admin/installation-searx.html#installation-basic">Step by step installation</a></p>
<h4 id="installation-des-paquets-prérequis">Installation des paquets prérequis</h4>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> <span class="nt">-H</span> apt-get <span class="nb">install</span> <span class="nt">-y</span> <span class="se">\</span>
python3-dev python3-babel python3-venv <span class="se">\</span>
uwsgi uwsgi-plugin-python3 <span class="se">\</span>
git build-essential libxslt-dev zlib1g-dev libffi-dev libssl-dev <span class="se">\</span>
shellcheck
</code></pre></div></div>
<p>Créer un utilisateur système</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> <span class="nt">-H</span> useradd <span class="nt">--shell</span> /bin/bash <span class="nt">--system</span> <span class="se">\</span>
<span class="nt">--home-dir</span> <span class="s2">"/usr/local/searx"</span> <span class="se">\</span>
<span class="nt">--comment</span> <span class="s1">'Privacy-respecting metasearch engine'</span> searx
<span class="nb">sudo</span> <span class="nt">-H</span> <span class="nb">mkdir</span> <span class="s2">"/usr/local/searx"</span>
<span class="nb">sudo</span> <span class="nt">-H</span> <span class="nb">chown</span> <span class="nt">-R</span> <span class="s2">"searx:searx"</span> <span class="s2">"/usr/local/searx"</span>
</code></pre></div></div>
<h4 id="installer-searx-et-les-dépendances">Installer searx et les dépendances</h4>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># basculer sur utilisateur searx</span>
<span class="nb">sudo</span> <span class="nt">-H</span> <span class="nt">-u</span> searx <span class="nt">-i</span>
<span class="c"># le prompt : searx@ouestyan:~$</span>
<span class="c"># cloner le dépôt</span>
git clone <span class="s2">"https://github.com/searx/searx.git"</span> <span class="s2">"/usr/local/searx/searx-src"</span>
<span class="c"># créer virtualenv</span>
python3 <span class="nt">-m</span> venv <span class="s2">"/usr/local/searx/searx-pyenv"</span>
<span class="nb">echo</span> <span class="s2">". /usr/local/searx/searx-pyenv/bin/activate"</span> <span class="o">&gt;&gt;</span> <span class="s2">"/usr/local/searx/.profile"</span>
</code></pre></div></div>
<p>Pour installer les dépendances de searx, quittez la session bash searx que vous avez ouverte ci-dessus et redémarrez-en une nouvelle.
Avant linstallation, vérifiez dabord si votre virtualenv provient du login (<code class="language-plaintext highlighter-rouge">~/.profile</code>) :</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hmsuser@ouestyan:~<span class="nv">$ </span><span class="nb">sudo</span> <span class="nt">-H</span> <span class="nt">-u</span> searx <span class="nt">-i</span>
<span class="o">(</span>searx-pyenv<span class="o">)</span> searx@ouestyan:~<span class="nv">$ </span><span class="nb">command</span> <span class="nt">-v</span> python <span class="o">&amp;&amp;</span> python <span class="nt">--version</span>
/usr/local/searx/searx-pyenv/bin/python
Python 3.9.2
<span class="c"># update pip's boilerplate ..</span>
pip <span class="nb">install</span> <span class="nt">-U</span> pip
pip <span class="nb">install</span> <span class="nt">-U</span> setuptools
pip <span class="nb">install</span> <span class="nt">-U</span> wheel
pip <span class="nb">install</span> <span class="nt">-U</span> pyyaml
<span class="c"># jump to searx's working tree and install searx into virtualenv</span>
<span class="o">(</span>searx-pyenv<span class="o">)</span> searx@ouestyan:~<span class="nv">$ </span><span class="nb">cd</span> <span class="s2">"/usr/local/searx/searx-src"</span>
<span class="o">(</span>searx-pyenv<span class="o">)</span> searx@ouestyan:~<span class="nv">$ </span>pip <span class="nb">install</span> <span class="nt">-e</span> <span class="nb">.</span>
</code></pre></div></div>
<h4 id="configuration">Configuration</h4>
<p>Ouvrez un deuxième terminal pour les tâches de configuration</p>
<p>Pour créer un /etc/searx/settings.yml initial, vous pouvez commencer par une copie du fichier <code class="language-plaintext highlighter-rouge">Origin : utils/templates/etc/searx/use_default_settings.yml</code>. Cette configuration utilise les paramètres par défaut de <code class="language-plaintext highlighter-rouge">Origin : searx/settings.yml</code> et est recommandée depuis la fusion du PR 2291.</p>
<p>Pour une installation minimale, configurez comme indiqué ci-dessous - remplacez searx@$(uname -n) par un nom de votre choix, définissez ultrasecretkey - et/ou modifiez /etc/searx/settings.yml selon vos besoins.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># paramètres searx</span>
<span class="nb">sudo</span> <span class="nt">-H</span> <span class="nb">mkdir</span> <span class="nt">-p</span> <span class="s2">"/etc/searx"</span>
<span class="nb">sudo</span> <span class="nt">-H</span> <span class="nb">cp</span> <span class="s2">"/usr/local/searx/searx-src/searx/settings.yml"</span> <span class="se">\</span>
<span class="s2">"/etc/searx/settings.yml"</span>
<span class="c"># minimal setup</span>
<span class="nb">sudo</span> <span class="nt">-H</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="nt">-e</span> <span class="s2">"s/ultrasecretkey/</span><span class="si">$(</span>openssl rand <span class="nt">-hex</span> 16<span class="si">)</span><span class="s2">/g"</span> <span class="s2">"/etc/searx/settings.yml"</span>
<span class="nb">sudo</span> <span class="nt">-H</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="nt">-e</span> <span class="s2">"s/{instance_name}/searx@</span><span class="si">$(</span><span class="nb">uname</span> <span class="nt">-n</span><span class="si">)</span><span class="s2">/g"</span> <span class="s2">"/etc/searx/settings.yml"</span>
</code></pre></div></div>
<p>Modifier le fichier de paramétrage <code class="language-plaintext highlighter-rouge">/etc/searx/settings.yml</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>general:
instance_name : "OuestSearx" # displayed name
ui:
theme_args :
oscar_style : logicodev-dark # default style of oscar
results_on_new_tab: True # Open result links in a new tab by default
# supprimer la ligne 'disabled : True' des éléments ci dessous ou positionner 'disabled : False'
- name : ddg definitions
engine : duckduckgo_definitions
shortcut : ddd
weight : 2
- name : duckduckgo
engine : duckduckgo
shortcut : ddg
- name : duckduckgo images
engine : duckduckgo_images
shortcut : ddi
timeout: 3.0
- name : startpage
engine : startpage
shortcut : sp
timeout : 6.0
disabled : False
additional_tests:
rosebud: *test_rosebud
# facultatif
# ajouter ligne 'disabled : True' sur certains éléments de la liste
- name : bing
engine : bing
shortcut : bi
disabled : True
- name : bing images
engine : bing_images
shortcut : bii
disabled : True
- name : bing news
engine : bing_news
shortcut : bin
disabled : True
- name : bing videos
engine : bing_videos
shortcut : biv
disabled : True
- name : wikidata
engine : wikidata
shortcut : wd
timeout : 3.0
weight : 2
tests: *tests_infobox
disabled : True
- name : google
engine : google
shortcut : go
use_mobile_ui: false
# additional_tests:
# android: *test_android
disabled : True
- name : google images
engine : google_images
shortcut : goi
# additional_tests:
# android: *test_android
# dali:
# matrix:
# query: ['Dali Christ']
# lang: ['en', 'de', 'fr', 'zh-CN']
# result_container:
# - ['one_title_contains', 'Salvador']
disabled : True
- name : google news
engine : google_news
shortcut : gon
# additional_tests:
# android: *test_android
disabled : True
- name : google videos
engine : google_videos
shortcut : gov
# additional_tests:
# android: *test_android
disabled : True
- name : google scholar
engine : google_scholar
shortcut : gos
disabled : True
</code></pre></div></div>
<h4 id="vérifier-en-local">Vérifier en local</h4>
<p>Pour vérifier votre configuration searx, vous pouvez activer le débogage et démarrer la webapp. Searx recherche un fichier de configuration dans lenvironnement exporté <code class="language-plaintext highlighter-rouge">$SEARX_SETTINGS_PATH</code></p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># dans le second terminal (hmsuser@ouestyan:~$)</span>
<span class="c"># enable debug ..</span>
<span class="nb">sudo</span> <span class="nt">-H</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="nt">-e</span> <span class="s2">"s/debug : False/debug : True/g"</span> <span class="s2">"/etc/searx/settings.yml"</span>
<span class="c"># start webapp</span>
<span class="nv">$ </span><span class="nb">sudo</span> <span class="nt">-H</span> <span class="nt">-u</span> searx <span class="nt">-i</span>
<span class="c"># prompt --&gt; (searx-pyenv) searx@ouestyan:~$ </span>
<span class="nb">cd</span> /usr/local/searx/searx-src
<span class="nb">export </span><span class="nv">SEARX_SETTINGS_PATH</span><span class="o">=</span><span class="s2">"/etc/searx/settings.yml"</span>
<span class="c"># lancement de la webapp</span>
python searx/webapp.py
</code></pre></div></div>
<p>Ouvrez un navigateur WEB et visitez http:// . Si vous êtes dans un conteneur ou dans un script, testez avec curl dans le second terminal</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl --location --verbose --head --insecure localhost:8888
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>* Trying 127.0.0.1:8888...
* Connected to localhost (127.0.0.1) port 8888 (#0)
&gt; GET / HTTP/1.1
&gt; Host: localhost:8888
&gt; User-Agent: curl/7.74.0
&gt; Accept: */*
&gt;
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
&lt; HTTP/1.0 200 OK
[...]
</code></pre></div></div>
<p>Si tout fonctionne bien, appuyez sur [CTRL-C] pour arrêter la webapp et désactiver loption de débogage dans settings.yml.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># disable debug</span>
<span class="nv">$ </span><span class="nb">sudo</span> <span class="nt">-H</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="nt">-e</span> <span class="s2">"s/debug : True/debug : False/g"</span> <span class="s2">"/etc/searx/settings.yml"</span>
</code></pre></div></div>
<p>Vous pouvez maintenant quitter searx en mode bash (entrez deux fois la commande exit). À ce stade, searx nest pas un daemon , uwsgi le permet.</p>
<h4 id="uwsgi">uwsgi</h4>
<p>Créer le fichier <code class="language-plaintext highlighter-rouge">/etc/uwsgi/apps-available/searx.ini</code></p>
<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[uwsgi]</span>
<span class="c"># uWSGI core
# ----------
#
# https://uwsgi-docs.readthedocs.io/en/latest/Options.html#uwsgi-core
</span>
<span class="c"># Who will run the code
</span><span class="py">uid</span> <span class="p">=</span> <span class="s">searx</span>
<span class="py">gid</span> <span class="p">=</span> <span class="s">searx</span>
<span class="c"># set (python) default encoding UTF-8
</span><span class="py">env</span> <span class="p">=</span> <span class="s">LANG=C.UTF-8</span>
<span class="py">env</span> <span class="p">=</span> <span class="s">LANGUAGE=C.UTF-8</span>
<span class="py">env</span> <span class="p">=</span> <span class="s">LC_ALL=C.UTF-8</span>
<span class="c"># chdir to specified directory before apps loading
</span><span class="py">chdir</span> <span class="p">=</span> <span class="s">/usr/local/searx/searx-src/searx</span>
<span class="c"># searx configuration (settings.yml)
</span><span class="py">env</span> <span class="p">=</span> <span class="s">SEARX_SETTINGS_PATH=/etc/searx/settings.yml</span>
<span class="c"># disable logging for privacy
</span><span class="py">disable-logging</span> <span class="p">=</span> <span class="s">true</span>
<span class="c"># The right granted on the created socket
</span><span class="py">chmod-socket</span> <span class="p">=</span> <span class="s">666</span>
<span class="c"># Plugin to use and interpreter config
</span><span class="py">single-interpreter</span> <span class="p">=</span> <span class="s">true</span>
<span class="c"># enable master process
</span><span class="py">master</span> <span class="p">=</span> <span class="s">true</span>
<span class="c"># load apps in each worker instead of the master
</span><span class="py">lazy-apps</span> <span class="p">=</span> <span class="s">true</span>
<span class="c"># load uWSGI plugins
</span><span class="py">plugin</span> <span class="p">=</span> <span class="s">python3,http</span>
<span class="c"># By default the Python plugin does not initialize the GIL. This means your
# app-generated threads will not run. If you need threads, remember to enable
# them with enable-threads. Running uWSGI in multithreading mode (with the
# threads options) will automatically enable threading support. This *strange*
# default behaviour is for performance reasons.
</span><span class="py">enable-threads</span> <span class="p">=</span> <span class="s">true</span>
<span class="c"># plugin: python
# --------------
#
# https://uwsgi-docs.readthedocs.io/en/latest/Options.html#plugin-python
</span>
<span class="c"># load a WSGI module
</span><span class="py">module</span> <span class="p">=</span> <span class="s">searx.webapp</span>
<span class="c"># set PYTHONHOME/virtualenv
</span><span class="py">virtualenv</span> <span class="p">=</span> <span class="s">/usr/local/searx/searx-pyenv</span>
<span class="c"># add directory (or glob) to pythonpath
</span><span class="py">pythonpath</span> <span class="p">=</span> <span class="s">/usr/local/searx/searx-src</span>
<span class="c"># speak to upstream
# -----------------
#
# Activate the 'http' configuration for filtron or activate the 'socket'
# configuration if you setup your HTTP server to use uWSGI protocol via sockets.
</span>
<span class="c"># using IP:
#
# https://uwsgi-docs.readthedocs.io/en/latest/Options.html#plugin-http
# Native HTTP support: https://uwsgi-docs.readthedocs.io/en/latest/HTTP.html
</span>
<span class="py">http</span> <span class="p">=</span> <span class="s">127.0.0.1:8888</span>
<span class="c"># using unix-sockets:
#
# On some distributions you need to create the app folder for the sockets::
#
# mkdir -p /run/uwsgi/app/searx
# chown -R searx:searx /run/uwsgi/app/searx
#
# socket = /run/uwsgi/app/searx/socket
</span>
<span class="c"># Cache
</span><span class="py">cache2</span> <span class="p">=</span> <span class="s">name=searxcache,items=2000,blocks=2000,blocksize=4096,bitmap=1</span>
</code></pre></div></div>
<p>Activer le fichier ini</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -H ln -s /etc/uwsgi/apps-available/searx.ini /etc/uwsgi/apps-enabled/
</code></pre></div></div>
<p>Démarrer le service</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -H service uwsgi start searx
</code></pre></div></div>
<p>Tester localement pour vérifier : <code class="language-plaintext highlighter-rouge">curl --location --verbose --head --insecure localhost:8888</code></p>
<p>Tester à partir dun poste distant<br />
Exécuter sur un poste distant</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh -L 9500:localhost:8888 hmsuser@45.145.166.178 -p 55178 -i /home/yann/.ssh/server32771
</code></pre></div></div>
<p>Sur le même poste , ouvrir le navigateur avec un lien <a href="http://localhost:9500">http://localhost:9500</a></p>
<p><img src="/images/searx.ouestyan.fr.png" alt="" width="600" /></p>
<p class="info">Après toute modification du fichier de configuration <code class="language-plaintext highlighter-rouge">/etc/searx/settings.yml</code>, il faut redémarrer le service <strong>uwsgi</strong> par la commande <code class="language-plaintext highlighter-rouge">sudo systemctl restart uwsgi</code></p>
<h4 id="nginx-proxy-searx">nginx proxy searx</h4>
<p>Le fichier de configuration nginx <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/searx.ouestyan.fr.conf</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
listen 80;
listen [::]:80;
server_name searx.ouestyan.fr;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name searx.ouestyan.fr;
include /etc/nginx/conf.d/security.conf.inc;
location / {
proxy_pass http://127.0.0.1:8888;
proxy_set_header Host $host;
proxy_set_header Connection $http_connection;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_buffering off;
}
}
</code></pre></div></div>
<p>Valider et recharger ginx</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://searx.ouestyan.fr">https://searx.ouestyan.fr</a></p>
<h3 id="nextcloud">Nextcloud</h3>
<p><a href="/2022/10/19/Nextcloud_Hub_3_(v25+).html">Nextcloud Hub 3 (v25+)</a></p>
<h4 id="transmission-torrent">Transmission Torrent</h4>
<p><a href="/2020/11/07/debian-transmission-daemon.html">Installation Transmission Torrent</a></p>
<h4 id="installer-transmission-daemon">Installer transmission-daemon</h4>
<p>Liste des commandes</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>transmission-cli transmission-common transmission-daemon
<span class="nb">sudo </span>systemctl stop transmission-daemon
<span class="nb">sudo </span>usermod <span class="nt">-a</span> <span class="nt">-G</span> debian-transmission <span class="nv">$USER</span>
</code></pre></div></div>
<h4 id="proxy-nginx">Proxy nginx</h4>
<p>Reverse proxy nginx <code class="language-plaintext highlighter-rouge">/etc/nginx/conf.d/transmission.ouestyan.fr.conf</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>upstream transmission {
server 127.0.0.1:9091;
}
server {
listen 80;
listen [::]:80;
server_name transmission.ouestyan.fr;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name transmission.ouestyan.fr;
include /etc/nginx/conf.d/security.conf.inc;
access_log /var/log/nginx/trans-access.log;
error_log /var/log/nginx/trans-error.log;
location / {
return 301 https://$server_name/transmission/;
location ^~ /transmission {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header Connection "";
proxy_pass_header X-Transmission-Session-Id;
location /transmission/rpc {
proxy_pass http://transmission;
}
location /transmission/web/ {
proxy_pass http://transmission;
}
location /transmission/upload {
proxy_pass http://transmission;
}
location /transmission/web/style/ {
alias /usr/share/transmission/web/style/;
}
location /transmission/web/javascript/ {
alias /usr/share/transmission/web/javascript/;
}
location /transmission/web/images/ {
alias /usr/share/transmission/web/images/;
}
location /transmission/ {
return 301 http://$server_name/transmission/web;
}
location /transmission/downloads/ {
alias /srv/transmission/completed/;
charset UTF-8;
autoindex on;
autoindex_exact_size off;
}
}
}
}
</code></pre></div></div>
<h4 id="dossiers-et-configuration">Dossiers et configuration</h4>
<p>Créer les différents dossiers pour le suivi des téléchargements</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo mkdir</span> <span class="nt">-p</span> /srv/transmission/<span class="o">{</span>watched,completed,progress<span class="o">}</span>
<span class="c"># les droits</span>
<span class="nb">chown </span>debian-transmission:www-data <span class="nt">-R</span> /srv/transmission/completed
<span class="nb">chown </span>debian-transmission:debian-transmission <span class="nt">-R</span> /srv/transmission/<span class="o">{</span>watched,progress<span class="o">}</span>
</code></pre></div></div>
<p>Modifier le fichier <code class="language-plaintext highlighter-rouge">/var/lib/transmission-daemon/info/settings.json</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"download-dir": "/srv/transmission/completed",
"incomplete-dir": "/srv/transmission/progress",
"rpc-authentication-required": true, // Activation de lauth par mot de passe
"rpc-url": "/",
"rpc-bind-address": "0.0.0.0", // 127.0.0.1 pour écouter en local
"rpc-enabled": true, // Activation de linterface web
"rpc-password": "MOT_DE_PASSE", // Tapez votre mot de passe, il sera salé au reload
"rpc-port": 9091, // Port découte
"rpc-url": "/transmission/", // Correspond à lURL daccès
"rpc-username": "UTILISATEUR", // Nom dutilisateur pour lauth
"rpc-host-whitelist": "",
"rpc-host-whitelist-enabled": false,
"rpc-whitelist": "127.0.0.1", // IPs à whitelist
"rpc-whitelist-enabled": true, // Activation de la whitelist
# en fin de fichier
"utp-enabled": true,
"watch-dir": "/srv/transmission/watched",
"watch-dir-enabled": true
}
</code></pre></div></div>
<p>le fichier json complet</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">"/srv/transmission/completed"</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">"/srv/transmission/progress"</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">"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">true</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">"127.0.0.1"</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">"{971fed709da0e448d0dec7ed65fe2600ce3ce916OvFJeoc6"</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">"yannick"</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,::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">true</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">18</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="p">,</span><span class="w">
</span><span class="nl">"watch-dir"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/srv/transmission/watched"</span><span class="p">,</span><span class="w">
</span><span class="nl">"watch-dir-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>Pour éviter lerreur “ transmission UDP Failed to set receive buffer …” , en mode su</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> <span class="nt">-s</span>
<span class="nb">echo</span> <span class="s2">"net.core.rmem_max = 4194304"</span> <span class="o">&gt;&gt;</span> /etc/sysctl.conf
<span class="nb">echo</span> <span class="s2">"net.core.wmem_max = 1048576"</span> <span class="o">&gt;&gt;</span> /etc/sysctl.conf
sysctl <span class="nt">-p</span>
</code></pre></div></div>
<p>Redémarrer le service</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl start transmission-daemon
</code></pre></div></div>
<p>A chaque modification (en mode su)</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>systemctl stop transmission-daemon
<span class="nb">rm</span> /var/lib/transmission-daemon/.config/transmission-daemon/settings.json
<span class="nb">rm</span> /etc/transmission-daemon/settings.json
<span class="c"># créer</span>
nano /var/lib/transmission-daemon/info/settings.json
</code></pre></div></div>
<h4 id="transmissionouestyanfr">transmission.ouestyan.fr</h4>
<p>Connexion sur le lien <a href="https://transmission.ouestyan.fr">https://transmission.ouestyan.fr</a><br />
<img src="/images/transmission.ouestyan.fr01.png" alt="" /><br />
Saisir “yannick” et son mot de passe</p>
<h3 id="test-de-sécurité">Test de sécurité</h3>
<p><a href="https://www.ssllabs.com/ssltest/index.html">Analyse SSL</a> contre le site Web pour trouver le score et la vulnérabilité essentielle.<br />
<img src="/images/ssllabs-ouestyan.fr.png" alt="" /><br />
<a href="https://www.ssllabs.com/ssltest/analyze.html?d=ouestyan.fr">https://www.ssllabs.com/ssltest/analyze.html?d=ouestyan.fr</a></p>
<p>Les entêtes <a href="https://securityheaders.com/">https://securityheaders.com/</a> <br />
<img src="/images/securityheaders-ouestyan.fr.png" alt="" /><br />
ouestyan.fr</p>
<p><img src="/images/securityheaders-cloud.ouestyan.fr.png" alt="" />
cloud.ouestyan.fr</p>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2022-07-21T00: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="/2022/06/24/Yunohost_Debian_Bullseye_image_de_nuage_Qcow2.html">Qemu/KVM - Virtuel Yunohost ouestyan.xyz (debian 11 image cloud Qcow2)</a></div><div class="next"><span>SUIVANT</span><a href="/2022/07/21/Matrix_Synapse_Home_Server.html">Matrix Synapse Home Server</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>