<!DOCTYPE html>

<html lang="en-US">

<head>
	<title>Penumbra &#8211; pe·num·bra  (pĭ-nŭm′brə) n. pl. pe·num·brae (-brē) or pe·num·bras 1. A partial shadow, as in an eclipse, between regions of complete shadow and complete illumination. See Synonyms at shade. 2. The grayish outer part of a sunspot.</title>
<meta name='robots' content='max-image-preview:large' />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="template" content="Author 1.47" />
<link rel='dns-prefetch' href='//fonts.googleapis.com' />
<link rel='dns-prefetch' href='//s.w.org' />
<link rel="alternate" type="application/rss+xml" title="Penumbra &raquo; Feed" href="https://blog.penumbra.be/feed/" />
<link rel="alternate" type="application/rss+xml" title="Penumbra &raquo; Comments Feed" href="https://blog.penumbra.be/comments/feed/" />
<script type="text/javascript">
window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/14.0.0\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/14.0.0\/svg\/","svgExt":".svg","source":{"concatemoji":"https:\/\/blog.penumbra.be\/wp-includes\/js\/wp-emoji-release.min.js?ver=6.0.2"}};
/*! This file is auto-generated */
!function(e,a,t){var n,r,o,i=a.createElement("canvas"),p=i.getContext&&i.getContext("2d");function s(e,t){var a=String.fromCharCode,e=(p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,e),0,0),i.toDataURL());return p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,t),0,0),e===i.toDataURL()}function c(e){var t=a.createElement("script");t.src=e,t.defer=t.type="text/javascript",a.getElementsByTagName("head")[0].appendChild(t)}for(o=Array("flag","emoji"),t.supports={everything:!0,everythingExceptFlag:!0},r=0;r<o.length;r++)t.supports[o[r]]=function(e){if(!p||!p.fillText)return!1;switch(p.textBaseline="top",p.font="600 32px Arial",e){case"flag":return s([127987,65039,8205,9895,65039],[127987,65039,8203,9895,65039])?!1:!s([55356,56826,55356,56819],[55356,56826,8203,55356,56819])&&!s([55356,57332,56128,56423,56128,56418,56128,56421,56128,56430,56128,56423,56128,56447],[55356,57332,8203,56128,56423,8203,56128,56418,8203,56128,56421,8203,56128,56430,8203,56128,56423,8203,56128,56447]);case"emoji":return!s([129777,127995,8205,129778,127999],[129777,127995,8203,129778,127999])}return!1}(o[r]),t.supports.everything=t.supports.everything&&t.supports[o[r]],"flag"!==o[r]&&(t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&t.supports[o[r]]);t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&!t.supports.flag,t.DOMReady=!1,t.readyCallback=function(){t.DOMReady=!0},t.supports.everything||(n=function(){t.readyCallback()},a.addEventListener?(a.addEventListener("DOMContentLoaded",n,!1),e.addEventListener("load",n,!1)):(e.attachEvent("onload",n),a.attachEvent("onreadystatechange",function(){"complete"===a.readyState&&t.readyCallback()})),(e=t.source||{}).concatemoji?c(e.concatemoji):e.wpemoji&&e.twemoji&&(c(e.twemoji),c(e.wpemoji)))}(window,document,window._wpemojiSettings);
</script>
<style type="text/css">
img.wp-smiley,
img.emoji {
	display: inline !important;
	border: none !important;
	box-shadow: none !important;
	height: 1em !important;
	width: 1em !important;
	margin: 0 0.07em !important;
	vertical-align: -0.1em !important;
	background: none !important;
	padding: 0 !important;
}
</style>
	<link rel='stylesheet' id='wp-block-library-css'  href='https://blog.penumbra.be/wp-includes/css/dist/block-library/style.min.css?ver=6.0.2' type='text/css' media='all' />
<style id='global-styles-inline-css' type='text/css'>
body{--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--duotone--dark-grayscale: url('#wp-duotone-dark-grayscale');--wp--preset--duotone--grayscale: url('#wp-duotone-grayscale');--wp--preset--duotone--purple-yellow: url('#wp-duotone-purple-yellow');--wp--preset--duotone--blue-red: url('#wp-duotone-blue-red');--wp--preset--duotone--midnight: url('#wp-duotone-midnight');--wp--preset--duotone--magenta-yellow: url('#wp-duotone-magenta-yellow');--wp--preset--duotone--purple-green: url('#wp-duotone-purple-green');--wp--preset--duotone--blue-orange: url('#wp-duotone-blue-orange');--wp--preset--font-size--small: 12px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 21px;--wp--preset--font-size--x-large: 42px;--wp--preset--font-size--regular: 16px;--wp--preset--font-size--larger: 37px;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}
</style>
<link rel='stylesheet' id='cptch_stylesheet-css'  href='https://blog.penumbra.be/wp-content/plugins/captcha/css/front_end_style.css?ver=4.4.5' type='text/css' media='all' />
<link rel='stylesheet' id='dashicons-css'  href='https://blog.penumbra.be/wp-includes/css/dashicons.min.css?ver=6.0.2' type='text/css' media='all' />
<link rel='stylesheet' id='cptch_desktop_style-css'  href='https://blog.penumbra.be/wp-content/plugins/captcha/css/desktop_style.css?ver=4.4.5' type='text/css' media='all' />
<link rel='stylesheet' id='ct-author-google-fonts-css'  href='//fonts.googleapis.com/css?family=Rokkitt%3A400%2C700%7CLato%3A400%2C700&#038;subset=latin%2Clatin-ext&#038;display=swap&#038;ver=6.0.2' type='text/css' media='all' />
<link rel='stylesheet' id='ct-author-font-awesome-css'  href='https://blog.penumbra.be/wp-content/themes/author/assets/font-awesome/css/all.min.css?ver=6.0.2' type='text/css' media='all' />
<link rel='stylesheet' id='ct-author-style-css'  href='https://blog.penumbra.be/wp-content/themes/poet/style.css?ver=6.0.2' type='text/css' media='all' />
<script type='text/javascript' src='https://blog.penumbra.be/wp-includes/js/jquery/jquery.min.js?ver=3.6.0' id='jquery-core-js'></script>
<script type='text/javascript' src='https://blog.penumbra.be/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.3.2' id='jquery-migrate-js'></script>
<!--[if IE 8]>
<script type='text/javascript' src='https://blog.penumbra.be/wp-content/themes/author/js/build/html5shiv.min.js?ver=6.0.2' id='ct-author-html5-shiv-js'></script>
<![endif]-->
<link rel="https://api.w.org/" href="https://blog.penumbra.be/wp-json/" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://blog.penumbra.be/xmlrpc.php?rsd" />
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="https://blog.penumbra.be/wp-includes/wlwmanifest.xml" /> 
<meta name="generator" content="WordPress 6.0.2" />
</head>

<body id="poet" class="home blog full-post">
		<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-dark-grayscale"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0 0.49803921568627" /><feFuncG type="table" tableValues="0 0.49803921568627" /><feFuncB type="table" tableValues="0 0.49803921568627" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-grayscale"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0 1" /><feFuncG type="table" tableValues="0 1" /><feFuncB type="table" tableValues="0 1" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-purple-yellow"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0.54901960784314 0.98823529411765" /><feFuncG type="table" tableValues="0 1" /><feFuncB type="table" tableValues="0.71764705882353 0.25490196078431" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-blue-red"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0 1" /><feFuncG type="table" tableValues="0 0.27843137254902" /><feFuncB type="table" tableValues="0.5921568627451 0.27843137254902" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-midnight"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0 0" /><feFuncG type="table" tableValues="0 0.64705882352941" /><feFuncB type="table" tableValues="0 1" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-magenta-yellow"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0.78039215686275 1" /><feFuncG type="table" tableValues="0 0.94901960784314" /><feFuncB type="table" tableValues="0.35294117647059 0.47058823529412" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-purple-green"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0.65098039215686 0.40392156862745" /><feFuncG type="table" tableValues="0 1" /><feFuncB type="table" tableValues="0.44705882352941 0.4" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-blue-orange"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="0.098039215686275 1" /><feFuncG type="table" tableValues="0 0.66274509803922" /><feFuncB type="table" tableValues="0.84705882352941 0.41960784313725" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg>	<a class="skip-content" href="#main">Skip to content</a>
		<div id="overflow-container" class="overflow-container">
			<div class="max-width">
				<div id="main-sidebar" class="main-sidebar">
																<header class="site-header" id="site-header" role="banner">
							<div id="title-container" class="title-container">
																<div class="container">
									<div id='site-title' class='site-title'><a href='https://blog.penumbra.be'><span class='screen-reader-text'>Penumbra</span><img class='logo' src='https://blog.penumbra.be/wp-content/uploads/2015/07/umbra.png' alt='Penumbra' /></a></div>									<p class="tagline">pe·num·bra  (pĭ-nŭm′brə) n. pl. pe·num·brae (-brē) or pe·num·bras 1. A partial shadow, as in an eclipse, between regions of complete shadow and complete illumination. See Synonyms at shade. 2. The grayish outer part of a sunspot.</p>								</div>
							</div>
							<button id="toggle-navigation" class="toggle-navigation" aria-expanded="false">
								<span class="screen-reader-text">open primary menu</span>
								<i class="fas fa-bars"></i>
							</button>
														<div id="menu-primary" class="menu-container menu-primary" role="navigation">
	<div class="menu-unset"><ul><li class="page_item page-item-117"><a href="https://blog.penumbra.be/howtos/">Howto&#8217;s</a></li></ul></div></div>						</header>
																<aside class="sidebar sidebar-primary" id="sidebar-primary" role="complementary">
		<h1 class="screen-reader-text">Sidebar</h1>
		<section id="categories-3" class="widget widget_categories"><h2 class="widget-title">Categories</h2>
			<ul>
					<li class="cat-item cat-item-1"><a href="https://blog.penumbra.be/category/howtos/">Howto&#039;s</a>
</li>
	<li class="cat-item cat-item-18"><a href="https://blog.penumbra.be/category/linux/">Linux</a>
</li>
	<li class="cat-item cat-item-81"><a href="https://blog.penumbra.be/category/live-migration/">Live migration</a>
</li>
	<li class="cat-item cat-item-34"><a href="https://blog.penumbra.be/category/monitoring/">Monitoring</a>
</li>
	<li class="cat-item cat-item-43"><a href="https://blog.penumbra.be/category/network/">Network</a>
</li>
	<li class="cat-item cat-item-14"><a href="https://blog.penumbra.be/category/news/">News</a>
</li>
	<li class="cat-item cat-item-76"><a href="https://blog.penumbra.be/category/patches/">Patches</a>
</li>
	<li class="cat-item cat-item-80"><a href="https://blog.penumbra.be/category/puppet-2/">Puppet</a>
</li>
	<li class="cat-item cat-item-54"><a href="https://blog.penumbra.be/category/security/">Security</a>
</li>
	<li class="cat-item cat-item-85"><a href="https://blog.penumbra.be/category/snippets/">Snippets</a>
</li>
	<li class="cat-item cat-item-39"><a href="https://blog.penumbra.be/category/virtualization/">Virtualization</a>
</li>
			</ul>

			</section><section id="archives-3" class="widget widget_archive"><h2 class="widget-title">Archives</h2>		<label class="screen-reader-text" for="archives-dropdown-3">Archives</label>
		<select id="archives-dropdown-3" name="archive-dropdown">
			
			<option value="">Select Month</option>
				<option value='https://blog.penumbra.be/2014/07/'> July 2014 &nbsp;(1)</option>
	<option value='https://blog.penumbra.be/2011/11/'> November 2011 &nbsp;(1)</option>
	<option value='https://blog.penumbra.be/2011/09/'> September 2011 &nbsp;(1)</option>
	<option value='https://blog.penumbra.be/2011/08/'> August 2011 &nbsp;(1)</option>
	<option value='https://blog.penumbra.be/2011/04/'> April 2011 &nbsp;(2)</option>
	<option value='https://blog.penumbra.be/2010/08/'> August 2010 &nbsp;(1)</option>
	<option value='https://blog.penumbra.be/2010/06/'> June 2010 &nbsp;(1)</option>
	<option value='https://blog.penumbra.be/2010/05/'> May 2010 &nbsp;(1)</option>
	<option value='https://blog.penumbra.be/2010/04/'> April 2010 &nbsp;(2)</option>
	<option value='https://blog.penumbra.be/2010/02/'> February 2010 &nbsp;(4)</option>
	<option value='https://blog.penumbra.be/2010/01/'> January 2010 &nbsp;(2)</option>
	<option value='https://blog.penumbra.be/2009/12/'> December 2009 &nbsp;(3)</option>

		</select>

<script type="text/javascript">
/* <![CDATA[ */
(function() {
	var dropdown = document.getElementById( "archives-dropdown-3" );
	function onSelectChange() {
		if ( dropdown.options[ dropdown.selectedIndex ].value !== '' ) {
			document.location.href = this.options[ this.selectedIndex ].value;
		}
	}
	dropdown.onchange = onSelectChange;
})();
/* ]]> */
</script>
			</section>	</aside>
									</div>
								<section id="main" class="main" role="main">
					<h1 class="screen-reader-text">Penumbra Posts</h1>	<div id="loop-container" class="loop-container">
		<div class="post-732 post type-post status-publish format-standard hentry category-howtos category-snippets tag-api tag-gitlab tag-ruby tag-snippet entry">
			<article>
		<div class='post-header'>
			<h2 class='post-title'>
				<a href="https://blog.penumbra.be/2014/07/creating-gitlab-group-projects-ruby-api/">Creating a bunch of Gitlab group projects using a Ruby wrapper</a>
			</h2>
			<span class="post-meta">
	Published by <span class='author'><a href='https://blog.penumbra.be/author/admin/'>Tom</a></span> on <span class='date'><a href='https://blog.penumbra.be/2014/07/'>July 15, 2014</a></span></span>		</div>
		<div class="post-content">
			<p>Just recently I needed a way to create +50 projects. Being the lazy ops guy I am, I quickly whipped this up using <a href="https://rubygems.org/gems/gitlab" title="narkoz/gitlab">NARKOZ&#8217;s Ruby wrapper</a>.</p>
<p>The tricky part was switching the context to a different namespace which was only possible using two undocumented parameters.<br />
Patch sent and <strike>awaiting approval</strike> merged.</p>
<pre>
#!/usr/bin/env ruby
require 'gitlab'

group_id = 5
token    = 'sekret'
endpoint = 'http://gitlab.tld/api/v3'

projects = %w(
  project-1
  project-2
  project-n
  ...
)

Gitlab.configure do |config|
  config.endpoint      = endpoint
  config.private_token = token
end

projects.each do |proj|
  Gitlab.create_project(
    proj,
    :description    => "Project #{proj}",
    :issues_enabled => true,
    :wiki_enabled   => false,
    :group_id       => group_id,
    :namespace_id   => group_id
  )
end
</pre>
					</div>
	</article>
	</div><div class="post-700 post type-post status-publish format-standard hentry category-howtos category-linux category-security tag-centos tag-centos-6 tag-ssh entry">
			<article>
		<div class='post-header'>
			<h2 class='post-title'>
				<a href="https://blog.penumbra.be/2011/11/centos-6-ignores-public-keys-by-default-when-selinux-is-enforced/">CentOS 6 ignores public keys by default when SELinux is enforced</a>
			</h2>
			<span class="post-meta">
	Published by <span class='author'><a href='https://blog.penumbra.be/author/admin/'>Tom</a></span> on <span class='date'><a href='https://blog.penumbra.be/2011/11/'>November 4, 2011</a></span></span>		</div>
		<div class="post-content">
			<p>&#8230; which is quite obviously ridiculous.<br />
Here&#8217;s a quick fix to restore public key login functionality without disabling SELinux:</p>
<pre># chmod 700 ~/.ssh
# chmod 600 ~/.ssh/*</pre>
					</div>
	</article>
	</div><div class="post-633 post type-post status-publish format-standard hentry category-howtos category-linux category-live-migration category-virtualization entry">
			<article>
		<div class='post-header'>
			<h2 class='post-title'>
				<a href="https://blog.penumbra.be/2011/09/live-p2v-migration-on-the-cheap/">Live P2V migration, on the cheap</a>
			</h2>
			<span class="post-meta">
	Published by <span class='author'><a href='https://blog.penumbra.be/author/admin/'>Tom</a></span> on <span class='date'><a href='https://blog.penumbra.be/2011/09/'>September 13, 2011</a></span></span>		</div>
		<div class="post-content">
			<p>Last week I performed a live physical to virtual migration for a customer. Ghetto style.<br />
I was actually surprised by its simplicity and how well it turned out in the end.</p>
<p>Basically what I did was boot the target server to a live environment in order to be able to have raw access to the disk. In this case I&#8217;ve used FAI&#8217;s Sysinfo mode, but booting any Linux Live CD would have worked equally well. After it&#8217;s booted I&#8217;ve created the the necessary partitions, created filesytems and mounted them. When those steps were done it was time to sync data and make the virtual system bootable.</p>
<p>Usually I would advise against this kind of migration but in this case there was only static data involved.<br />
It worked out well for me, but your mileage may vary.</p>
<p>Alright here&#8217;s what I did step by step&#8230;</p>
<p><strong>1. Backup partition layout and MBR </strong></p>
<pre>source:~ # sfdisk -d /dev/sda &gt; /tmp/source-partitions
source:~ # dd if=/dev/sda of=/tmp/source-mbr.img bs=512 count=1
source:~ # scp /tmp/source-* target:/tmp/</pre>
<p><strong>2. Restore partition layout and MBR </strong></p>
<pre>target:~ # dd if=/tmp/source-mbr.img of=/dev/sda bs=446 count=1
target:~ # sfdisk /dev/xvda &lt; /tmp/source-partitions</pre>
<p><strong>3. Create a filesystem on each partition </strong></p>
<pre>target:~ # for partition in xvda1 xvda6 xvda7 xvda8 xvda9 xvda10; do mkfs.ext4 /dev/$partition; done</pre>
<p><strong>4. Create a swap space</strong></p>
<pre>mkswap /dev/xvda2
swapon /dev/xvda2</pre>
<p><strong>5. Mount the newly created partitions </strong></p>
<pre>target:~ # mount /dev/xvda1 /mnt/tmp/
target:~ # mount /dev/xvda6 /mnt/tmp/var/
target:~ # mount /dev/xvda7 /mnt/tmp/tmp/
target:~ # mount /dev/xvda8 /mnt/tmp/usr
target:~ # mount /dev/xvda9 /mnt/tmp/home/
target:~ # mount /dev/xvda10 /mnt/tmp/data/</pre>
<p><strong>6. Synchronise data from source to target </strong></p>
<pre>target:~ # for i in $(seq 1 10);
do
rsync -av --delete --progress \
--exclude=/dev \
--exclude=/sys \
--exclude=/proc \
--exclude=/mnt/ \
--exclude=/media/ \
source:/* /mnt/tmp/;
done
target:~ #</pre>
<p>Repeat this step until you&#8217;re confident nothing has changed anymore.</p>
<p><strong>7. Enter the synchronized environment </strong></p>
<pre>target:~ # mount -t proc none /mnt/tmp/proc
target:~ # mount --rbind /dev /mnt/tmp/dev

target:~ # chroot /mnt/tmp /bin/bash
chroot:~ # source /etc/profile</pre>
<p><strong>8. Fix fstab entries</strong></p>
<p>(only for Xen vm&#8217;s)</p>
<pre>chroot:~ # sed -i 's+/dev/sda+/dev/xvda+g' /etc/fstab
chroot:~ # vim /etc/fstab</pre>
<p><strong>9. Fix network settings </strong></p>
<pre>chroot:~ # vim /etc/network/interfaces</pre>
<p><strong>10. Make the system bootable </strong></p>
<pre>chroot:~ # grep -v rootfs /proc/mounts > /etc/mtab
chroot:~ # grub-install --no-floppy /dev/xvda
chroot:~ # update-grub</pre>
<p>Once you&#8217;ve run the above commands it&#8217;s time to exit the chroot, unmount all partitions and reboot<br />
into your migrated environment. Enjoy!</p>
					</div>
	</article>
	</div><div class="post-591 post type-post status-publish format-standard hentry category-howtos category-linux category-news category-puppet-2 entry">
			<article>
		<div class='post-header'>
			<h2 class='post-title'>
				<a href="https://blog.penumbra.be/2011/08/dynamic-lookup-is-deprecated-when-using-facts-in-templates/">&#8220;Dynamic lookup is deprecated. Support will be removed in Puppet 2.8.&#8221; when using facts in templates</a>
			</h2>
			<span class="post-meta">
	Published by <span class='author'><a href='https://blog.penumbra.be/author/admin/'>Tom</a></span> on <span class='date'><a href='https://blog.penumbra.be/2011/08/'>August 11, 2011</a></span></span>		</div>
		<div class="post-content">
			<p>Recently ran into some of these when running Puppet 2.7.x:</p>
<pre>warning: Dynamic lookup of $variable is deprecated. Support 
will be removed in Puppet 2.8.  Use a fully-qualified variable
name (e.g., $classname::variable) or parameterized classes.</pre>
<p>The solution was pretty obvious and it&#8217;s easy to fix because the solution is mentioned in the warning. However the warning fails to mention what to do with <a href="http://www.puppetlabs.com/puppet/related-projects/facter/" title="Facter">Facter</a> facts inside ERB templates. Figuring out how to fix this took me quite a while although it&#8217;s easy too.</p>
<p>Let&#8217;s start by taking a look at this snippet:</p>
<pre>
NameVirtualHost <%= 'ipaddress' %>:80
< VirtualHost <%= 'ipaddress' %>:80 >
	Servername www.example.com
	DocumentRoot /var/www/vhosts/example.com
	ServerAdmin info@example.com
</pre>
<p>If we&#8217;d apply this template in a manifest using Puppet 2.7.x we would run into the warning mentioned above because the IP address fact is out of scope. In order to avoid this we use lookupvar for <a href="http://www.puppetlabs.com/puppet/related-projects/facter/" title="Facter">Facter</a> facts:</p>
<pre>NameVirtualHost <%= scope.lookupvar('ipaddress') %>:80
< VirtualHost <%= scope.lookupvar('ipaddress') %>:80 >
	Servername www.example.com
	DocumentRoot /var/www/vhosts/example.com
	ServerAdmin info@example.com
</pre>
					</div>
	</article>
	</div><div class="post-544 post type-post status-publish format-standard hentry category-news category-patches category-puppet-2 tag-apache tag-mod_passenger tag-puppet tag-puppetmaster entry">
			<article>
		<div class='post-header'>
			<h2 class='post-title'>
				<a href="https://blog.penumbra.be/2011/04/puppetmaster-passenger-session-ticket-a-tlsv1-alert-decrypt-error/">puppetmaster-passenger session ticket A: tlsv1 alert decrypt error</a>
			</h2>
			<span class="post-meta">
	Published by <span class='author'><a href='https://blog.penumbra.be/author/admin/'>Tom</a></span> on <span class='date'><a href='https://blog.penumbra.be/2011/04/'>April 6, 2011</a></span></span>		</div>
		<div class="post-content">
			<p>There is a bug in the default puppetmaster vhost that&#8217;s included in Ubuntu-10.10&#8217;s puppetmaster-passenger package.</p>
<pre># puppetd --server puppet.fqdn --waitforcert 60 --no-usecacheonfailure
err: Could not retrieve catalog from remote server: SSL_connect returned=1 errno=0 state=SSLv3 read server session ticket A: tlsv1 alert decrypt error
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
</pre>
<p>Lucky for us this is easily fixed using the patch below.<br />
If you have trouble copy/pasting it, here&#8217;s a direct link: <em><a href="http://blog.penumbra.be/files/apache_passenger_tlsv1.patch">apache_passenger_tlsv1.patch</a></em>.</p>
<pre>*** puppetmaster	Mon Feb  21 15:25:28 2011
--- puppetmaster.new	Mon Feb  21 15:25:13 2011
***************
*** 13,19 ****
          SSLCertificateChainFile /var/lib/puppet/ssl/certs/ca.pem
          # If Apache complains about invalid signatures on the CRL, you can try disabling
          # CRL checking by commenting the next line, but this is not recommended.
!         SSLCARevocationFile     /var/lib/puppet/ssl/ca/ca_crl.pem
          # Set to require if this puppetmaster doesn't issue certificates
          # to puppet clients.
          # NB: this requires SSLCACertificateFile /var/lib/puppet/ssl/certs/ca.pem
--- 13,20 ----
          SSLCertificateChainFile /var/lib/puppet/ssl/certs/ca.pem
          # If Apache complains about invalid signatures on the CRL, you can try disabling
          # CRL checking by commenting the next line, but this is not recommended.
!         # default: SSLCARevocationFile     /var/lib/puppet/ssl/ca/ca_crl.pem
!         SSLCARevocationPath     /var/lib/puppet/ssl/ca/crl
          # Set to require if this puppetmaster doesn't issue certificates
          # to puppet clients.
          # NB: this requires SSLCACertificateFile /var/lib/puppet/ssl/certs/ca.pem
</pre>
<p>You can apply it using:</p>
<pre># patch -i apache_passenger_tlsv1.patch \
/etc/apache2/sites-available/puppetmaster
</pre>
<p>I&#8217;ve already filed a bug and supplied the solution a while ago. It has been confirmed but it&#8217;s still not in the default repositories yet, which is beyond my reach.</p>
					</div>
	</article>
	</div><div class="post-524 post type-post status-publish format-standard hentry category-howtos category-news tag-bugfix tag-osx-10-6-7 tag-vagrant tag-veewee entry">
			<article>
		<div class='post-header'>
			<h2 class='post-title'>
				<a href="https://blog.penumbra.be/2011/04/veewee-0-1-16-we-tried-to-create-a-box-or-a-box-was-here-before-but-now-its-gone/">Veewee 0.1.16: &#8216;we tried to create a box or a box was here before but now it&#8217;s gone&#8217;</a>
			</h2>
			<span class="post-meta">
	Published by <span class='author'><a href='https://blog.penumbra.be/author/admin/'>Tom</a></span> on <span class='date'><a href='https://blog.penumbra.be/2011/04/'>April 6, 2011</a></span></span>		</div>
		<div class="post-content">
			<p>A few days ago I ran into a strange error using <a href="https://github.com/jedi4ever/veewee">Veewee</a> 0.1.16 on Mac OSX 10.6.7. Due to this error I couldn&#8217;t create a single basebox. No matter what I did. However thanks to <a href="https://twitter.com/#!/patrickdebois">@patrickdebois&#8217;</a> speedy support it was easily fixed.</p>
<p>For those who can&#8217;t wait for the fix to enter upstream I&#8217;ve included the patch below.<br />
And also a direct link <em><a href="http://blog.penumbra.be/files/veewee_shell_osx10.6.7.patch">veewee_shell_osx10.6.7.patch</a></em>, if you have trouble copy/pasting it.</p>
<pre>
# cat veewee_shell_osx10.6.7.patch 
*** shell.rb	Wed Apr  6 15:09:59 2011
--- shell.rb.new	Wed Apr  6 15:10:03 2011
***************
*** 3,16 ****
  module Veewee
    class Shell
   
!     def self.execute(command,options = {})
  
        IO.popen("#{command}") { |f| print f }
      end
      
      #pty allows you to gradually see the output of a local command
      #http://www.shanison.com/?p=415
!       def self.execute2(command, options = {} )
          require "pty"
              begin
                PTY.spawn( command ) do |r, w, pid|
--- 3,16 ----
  module Veewee
    class Shell
   
!     def self.execute2(command,options = {})
  
        IO.popen("#{command}") { |f| print f }
      end
      
      #pty allows you to gradually see the output of a local command
      #http://www.shanison.com/?p=415
!       def self.execute(command, options = {} )
          require "pty"
              begin
                PTY.spawn( command ) do |r, w, pid|
</pre>
<p>You can apply it using:</p>
<pre>
# sudo patch -i shell_osx10.6.7.patch \
/opt/local/lib/ruby/gems/1.8/gems/veewee-0.1.16/lib/veewee/shell.rb
</pre>
					</div>
	</article>
	</div><div class="post-463 post type-post status-publish format-standard hentry category-howtos category-linux category-network category-news tag-esx tag-esxi tag-linux tag-opensuse tag-rhel6 tag-template tag-ubuntu tag-udev tag-vsphere tag-vwware entry">
			<article>
		<div class='post-header'>
			<h2 class='post-title'>
				<a href="https://blog.penumbra.be/2010/08/udev-ubuntu-vmware-vsphere/">Fixing strange device names using Ubuntu templates on VMware ESX or vSphere</a>
			</h2>
			<span class="post-meta">
	Published by <span class='author'><a href='https://blog.penumbra.be/author/admin/'>Tom</a></span> on <span class='date'><a href='https://blog.penumbra.be/2010/08/'>August 23, 2010</a></span></span>		</div>
		<div class="post-content">
			<p>If you regularly deploy Ubuntu VM templates on your VMware ESX(i) or VMware vSphere boxes you will probably run into strange network device numbers. This is caused by a udev rule. This problem has been confirmed to exist in Ubuntu 9.04, 9.10 and 10.04. I haven&#8217;t had the time to check out other versions of Ubuntu. It&#8217;s also still existing in RHEL 6 and Scientific Linux 6.</p>
<p>As you can see below we have two ethernet devices: eth4 and eth5 instead of the usual eth0<br />
and eth1.</p>
<pre>root@box:~# ifconfig | grep Link
lo        Link encap:Local Loopback  
<strong>eth4</strong>  Link encap:UNSPEC  HWaddr  
<strong>eth5</strong>  Link encap:UNSPEC  HWaddr  
root@box:~#
</pre>
<p>Lucky for us it&#8217;s very simple to persistenly assign the correct device names to the corresponding mac address.</p>
<pre>root@box:~# grep eth4 /etc/udev/rules.d/70-persistent-net.rules 
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", 
ATTR{address}=="00:11:22:33:44:55", ATTR{dev_id}=="0x0", 
ATTR{type}=="1", KERNEL=="eth*", <strong>NAME="eth4"</strong>
root@box:~#</pre>
<p>Use your favorite editor to edit /etc/udev/rules.d/70-persistent-net.rules.<br />
Replace <strong>NAME=&#8221;eth4&#8243;</strong> with <strong>NAME=&#8221;eth0&#8243;</strong> and do the same with eth5.<br />
Save the config file, reboot and you&#8217;re done!</p>
<p><strong>Update:</strong><br />
After writing this guide I&#8217;ve also found this issue to exist on other udev-based distro&#8217;s (e.g. OpenSUSE) and other VMware products too (e.g. Fusion and Workstation). The same fix applies, so no worries there.</p>
					</div>
	</article>
	</div><div class="post-466 post type-post status-publish format-standard hentry category-howtos category-news tag-3g tag-homescreen-wallpaper tag-iphone tag-jailbreak tag-multitasking entry">
			<article>
		<div class='post-header'>
			<h2 class='post-title'>
				<a href="https://blog.penumbra.be/2010/06/iphone-3g-ios4-multitasking/">Enabling Multitasking and Homescreen wallpapers on the iPhone 3G iOS4</a>
			</h2>
			<span class="post-meta">
	Published by <span class='author'><a href='https://blog.penumbra.be/author/admin/'>Tom</a></span> on <span class='date'><a href='https://blog.penumbra.be/2010/06/'>June 28, 2010</a></span></span>		</div>
		<div class="post-content">
			<p>For those who are still using the trusty old iPhone 3G the recent iOS4 release didn&#8217;t really bring much interesting features. Among the list of long-awaited features one in particular wasn&#8217;t available on the 3G: multitasking.</p>
<p>Another feature that wasn&#8217;t available is the Homescreen wallpaper option. Although it was possible to overcome this on the old firmwares using tools like Winterboard. Unfortunately Winterboard hasn&#8217;t been released for the new iOS4 just yet.</p>
<p>Luckily for us poor saps Apple has only decided to disable these features and not to remove them completely from the iOS4 firmware. Both features can be enabled easily by editing just one .plist file.</p>
<p>First you&#8217;ll need to Jailbreak your device using PwnageTool4. It&#8217;s a self explanatory tool, so there&#8217;s no use in guiding you through these steps. Be sure to install OpenSSH using Cydia once the Jailbreak has been executed.</p>
<p>Now SCP into your device and transfer the file called N82AP.plist.</p>
<pre># scp -P22 root@10.0.3.22:/System/Library/CoreServices/
SpringBoard.app/N82AP.plist /tmp/
</pre>
<p>Now use the XCode Property List Editor to edit the plist file. XCode can be obtained freely from the Apple Dev site. Add both &#8220;multitasking&#8221; and &#8220;homescreen-wallpaper&#8221; entries as booleans to Root &#8211; capabilities.<br />
<img alt="plist editor" src="https://blog.penumbra.be/files/img/iphone3g_mutitasking_wallpaper_plist.png" title="plist editor" width="544" height="529" class="aligncenter" /></p>
<p>Save, exit and transfer your edited N82AP.plist file back to your device like this:</p>
<pre># scp -P22 N82AP.plist root@10.0.3.22:/System/Library/
CoreServices/SpringBoard.app/
</pre>
<p>Reboot your iPhone. Both Multitasking and Homescreen wallpaper are now enabled!</p>
<p><img loading="lazy" alt="" src="https://blog.penumbra.be/files/img/iphone3g_mutitasking_enabled.png" title="iPhone 3G multitasking enabled"  class="aligncenter" width="320" height="480" /></p>
<p>Enjoy!</p>
					</div>
	</article>
	</div><div class="post-394 post type-post status-publish format-standard hentry category-howtos category-linux category-news category-security tag-apache tag-attack-mitigation tag-mpm-itk tag-mpm-prefork tag-security tag-shared-hosting entry">
			<article>
		<div class='post-header'>
			<h2 class='post-title'>
				<a href="https://blog.penumbra.be/2010/05/hosting-attack-mitigation-p1/">Shared hosting attack mitigation, part 1: Apache MPM-ITK</a>
			</h2>
			<span class="post-meta">
	Published by <span class='author'><a href='https://blog.penumbra.be/author/admin/'>Tom</a></span> on <span class='date'><a href='https://blog.penumbra.be/2010/05/'>May 2, 2010</a></span></span>		</div>
		<div class="post-content">
			<p>When it comes to shared hosting we often get to see the same patterns and CMS installs over and over again. We have the big guns: Joomla, WordPress, Drupal, Typo3. And then there are smaller guys like e107, eZ Publish, XOOPS. Occasionally we run into TinyCMS, MiaCMS or even a YupiCMS install. They all have several things in common: they all try to be user friendly and easy to set-up. They&#8217;ll make you have a website online in a matter of hours or even minutes. So far, so good.</p>
<p>But what about patching? People tend to neglect to keep their installs up-to-date. We often get to hear people are afraid to break their corporate website or they rely on the web agency who built their website. However most of these agencies don&#8217;t want to take the risk either, unless there&#8217;s a hefty monthly support fee involved. And even when there is one they don&#8217;t always get around to do so.</p>
<p>This might become a serious problem for anyone running (on) a shared hosting server. XSS attacks, SQL injection and other kinds of intrusion might lead to collateral damage. Other people&#8217;s sites just might get attacked too. By default any vHost is readable and more importantly <em>writeable</em> by the user that is used to run PHP scripts. In most cases this is the Apache user.</p>
<p>If we can run our hosted PHP scripts using a separate user for each vHost we should be able to mitigate a large amount of common attacks towards other vHosts! However it isn&#8217;t feasible to run each hosting inside a separate chrooted environment. It would take too much time to set-up and it&#8217;s rather complex to patch it.</p>
<p>This is where Apache MPM-ITK comes into play. It&#8217;s an MPM (Multi-Processing Module) that is able to use a separate uid/guid per vHost without the need for a separate chroot for each hosting.</p>
<p>Enough chit-chat. Let&#8217;s get to it.</p>
<p>Install a default LAMP stack:</p>
<pre># apt-get install apache2-mpm-itk apache2-utils apache2.2-common 
defoma fontconfig-config libapache2-mod-php5 libapr1 libaprutil1 
libexpat1 libfontconfig1 libfreetype6 libgd2-xpm libjpeg62 
libltdl3 libmcrypt4 libpq5 libt1-5 libxpm4 openssl ssl-cert 
openssl-blacklist php5-common php5-cli php5-gd php5-mcrypt 
php5-mysql ttf-dejavu ttf-dejavu-core ttf-dejavu-extra
</pre>
<p>If you&#8217;re already running a LAMP stack it&#8217;s easy to replace the default MPM:</p>
<pre># apt-get remove apache2-mpm-prefork
# apt-get install apache2-mpm-itk
</pre>
<p>Configuring MPM ITK isn&#8217;t exactly brain surgery. Simply add an IfModule statement to your existing vHost config or use the following example to create a new one:</p>
<pre># cat /etc/apache2/sites-available/vhost-example.conf
&lt;VirtualHost *:80&gt;
<strong>  &lt;IfModule mpm_itk_module&gt;
    AssignUserId example example
  &lt;/IfModule&gt;</strong>

  DocumentRoot /var/www/vhosts/example/public_html/
  ServerName example.com
  ServerAlias www.example.com

  CustomLog /var/www/vhosts/example/logs/access_log combined
  ErrorLog /var/www/vhosts/example/logs/error_log

  ScriptAlias /cgi-bin/ /var/www/vhosts/example/cgi-bin/
  DirectoryIndex index.php index.html index.htm

  &lt;Directory "/var/www/vhosts/example/cgi-bin/"&gt;
    Options +ExecCGI
    AllowOverride none
  &lt;/Directory&gt;
&lt;/VirtualHost&gt;
</pre>
<p>Don&#8217;t forget to create the default user and appropriate folders. Change the permissions afterwards:</p>
<pre># useradd example
# mkdir -p /var/www/vhosts/example/
# mkdir -p /var/www/vhosts/example/public_html/
# mkdir -p /var/www/vhosts/example/cgi-bin/
# mkdir -p /var/www/vhosts/example/logs/
# chown -R example:example /var/www/vhosts/example/
</pre>
<p>Once this has been done, enable your website and test the configuration before reloading the Apache daemon:</p>
<pre># a2ensite vhost-example.conf
Enabling site vhost-example.conf.
Run '/etc/init.d/apache2 reload' to activate new configuration!

# apache2ctl configtest
Syntax OK

# /etc/init.d/apache2 reload
Reloading web server config: apache2.
</pre>
<p>And that&#8217;s it! Use phpinfo(); if you want to check you&#8217;re actually running on MPM ITK. It should be listed in Loaded Modules. Another way to verify is using ps or top. The PHP scripts for your newly created vHost should be running on it&#8217;s own separate user:</p>
<pre>15059 <strong>example</strong> 20  0 24596 5624 2468 R  0.7  3.9  0:00.02 apache2
15060 <strong>example</strong> 20  0 24596 5496 2340 R  0.7  3.8  0:00.02 apache2
15061 <strong>example</strong> 20  0 24596 5412 2256 R  0.7  3.7  0:00.02 apache2
15062 <strong>example</strong> 20  0 24596 5360 2204 R  0.7  3.7  0:00.02 apache2
</pre>
<p>There is obviously a performance penalty involved when using MPM ITK.<br />
I&#8217;ve compared both the default MPM Prefork and MPM ITK using Apache Bench and phpinfo() serving the content:</p>
<pre># ab -n 2000 -c 4 http://example.com/index.php
</pre>
<p><a href="http://blog.penumbra.be/wp-content/uploads/2010/05/mpm_prefork_vs_mpm_itk.png"><img loading="lazy" class="size-full wp-image-449 alignnone" style="border: 0pt none;" title="mpm prefork vs mpm itk" src="http://blog.penumbra.be/wp-content/uploads/2010/05/mpm_prefork_vs_mpm_itk.png" alt="mpm prefork vs mpm itk" width="519" height="237" srcset="https://blog.penumbra.be/wp-content/uploads/2010/05/mpm_prefork_vs_mpm_itk.png 577w, https://blog.penumbra.be/wp-content/uploads/2010/05/mpm_prefork_vs_mpm_itk-300x136.png 300w" sizes="(max-width: 519px) 100vw, 519px" /></a></p>
<p>Please do bear in mind that this was tested on low power hardware (Atom 1.6GHz cpu).</p>
					</div>
	</article>
	</div><div class="post-362 post type-post status-publish format-standard hentry category-howtos category-linux category-monitoring tag-cyrus tag-open-relay tag-postfix tag-sasl entry">
			<article>
		<div class='post-header'>
			<h2 class='post-title'>
				<a href="https://blog.penumbra.be/2010/04/authenticated-smtp-postfix/">Authenticated SMTP with Postfix on CentOS, the easy way</a>
			</h2>
			<span class="post-meta">
	Published by <span class='author'><a href='https://blog.penumbra.be/author/admin/'>Tom</a></span> on <span class='date'><a href='https://blog.penumbra.be/2010/04/'>April 27, 2010</a></span></span>		</div>
		<div class="post-content">
			<p>This will be more of a future reference than an actual howto. It&#8217;s far from feature complete but it will get you started on authenticated SMTP sessions using Postfix. Quick &amp; dirty.</p>
<p>Installing Postfix and SASL on CentOS:</p>
<pre># yum install postfix
# yum install cyrus-sasl cyrus-sasl-plain cyrus-sasl-md5</pre>
<p>Let&#8217;s move on to the configuration now. Below you will find my default template<br />
for /etc/postfix/main.cf:</p>
<pre># cat /etc/postfix/main.cf
smtpd_banner = $myhostname ESMTP $mail_name

myhostname = example.tld
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = example.tld
mydestination = example.tld, localhost.localdomain, localhost
transport_maps =
relayhost =
mynetworks = 127.0.0.1/32
#mynetworks = hash:/etc/postfix/networks

smtpd_sasl_path = sasl2/smtpd.conf
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = example.tld
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes

recipient_delimiter = +
inet_interfaces = all

smtpd_recipient_restrictions = permit_mynetworks,
        permit_sasl_authenticated,
        reject_unauth_destination,
        reject_rbl_client opm.blitzed.org,
        reject_rbl_client list.dsbl.org,
        reject_rbl_client sbl.spamhaus.org,
        reject_rbl_client cbl.abuseat.org,
        reject_rbl_client dul.dnsbl.sorbs.net</pre>
<p>Use smtpd_recipient_restrictions to make sure you&#8217;re not running an Open Relay server accepting spam from anyone. It will accept unauthenticated sessions originating from localhost only. However authenticated sessions are generally allowed.</p>
<p>Make sure your Postfix daemon is actually able to communicate with the sasl daemon.<br />
To accomplish this append this to /etc/postfix/master.cf:</p>
<pre># cat /etc/postfix/master.cf
submission inet n       -       n       -       -       smtpd
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_sasl_local_domain=example.tld
  -o header_checks=
  -o body_checks=
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination
  -o smtpd_sasl_security_options=noanonymous,noplaintext
  -o smtpd_sasl_tls_security_options=noanonymous</pre>
<p>Next up we&#8217;re going to add our users to the sasl database:</p>
<pre># saslpasswd2 -c -u $hostname $user</pre>
<p>While we&#8217;re at it, it might be a good idea to fix permissions on the sasl database. Otherwise Postfix will be unable to read from it or write to it.</p>
<pre># chown postfix:postfix /etc/sasldb2
# chmod 660 /etc/sasldb2</pre>
<p>We&#8217;re almost there. To configure the sasl daemon itself:</p>
<pre># cat /usr/lib/sasl2/smtpd.conf
pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5</pre>
<pre># cat /usr/lib/sasl/smtpd.conf
pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5</pre>
<p>And finally restart the daemons.</p>
<pre># /etc/init.d/sasld restart
# /etc/init.d/postfix restart</pre>
<p>Be sure to confirm it&#8217;s working using both your default mail client and /var/log/maillog.</p>
<p>Enjoy!</p>
					</div>
	</article>
	</div>	</div>

	<nav class="navigation pagination" aria-label="Posts">
		<h2 class="screen-reader-text">Posts navigation</h2>
		<div class="nav-links"><span aria-current="page" class="page-numbers current">1</span>
<a class="page-numbers" href="https://blog.penumbra.be/page/2/">2</a>
<a class="next page-numbers" href="https://blog.penumbra.be/page/2/">Next</a></div>
	</nav></section><!-- .main -->
    <footer class="site-footer" role="contentinfo">
                <div class="design-credit">
            <span>
                <a href="https://www.competethemes.com/author/" rel="nofollow">Author WordPress Theme</a> by Compete Themes            </span>
        </div>
    </footer>
</div><!-- .max-width -->
</div><!-- .overflow-container -->
<script type='text/javascript' id='ct-author-js-js-extra'>
/* <![CDATA[ */
var ct_author_objectL10n = {"openPrimaryMenu":"open primary menu","closePrimaryMenu":"close primary menu","openChildMenu":"open child menu","closeChildMenu":"close child menu"};
/* ]]> */
</script>
<script type='text/javascript' src='https://blog.penumbra.be/wp-content/themes/author/js/build/production.min.js?ver=6.0.2' id='ct-author-js-js'></script>
<!--[if IE 8]>
<script type='text/javascript' src='https://blog.penumbra.be/wp-content/themes/author/js/build/respond.min.js?ver=6.0.2' id='ct-author-respond-js'></script>
<![endif]-->
</body>
</html>