<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Developers Archives | Clever Cloud</title>
	<atom:link href="https://stagingv6.cleverapps.io/blog/tag/developers/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>From Code to Product</description>
	<lastBuildDate>Fri, 27 Oct 2023 10:25:15 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2023/03/cropped-cropped-favicon-32x32.png</url>
	<title>Developers Archives | Clever Cloud</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Bun: how to host your apps on Clever Cloud</title>
		<link>https://stagingv6.cleverapps.io/blog/features/2023/09/22/bun-on-clever-cloud/</link>
		
		<dc:creator><![CDATA[David Legrand]]></dc:creator>
		<pubDate>Fri, 22 Sep 2023 15:01:59 +0000</pubDate>
				<category><![CDATA[Features]]></category>
		<category><![CDATA[clevercloud]]></category>
		<category><![CDATA[Developers]]></category>
		<guid isPermaLink="false">https://stagingv6.cleverapps.io/?p=10008</guid>

					<description><![CDATA[<p><img width="1480" height="740" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2023/09/banner-bun-on-clever-cloud.svg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="BANNIER bun" decoding="async" fetchpriority="high" /></p><!-- wp:paragraph -->
<p><strong>For more than a year now, Jarred Sumner and his team have been working on a new open source JavaScript runtime: <a href="https://github.com/oven-sh/bun" target="_blank" rel="noreferrer noopener">Bun</a>. <strong> It's touted as more efficient and feature-rich than current solutions such as Node.js or Deno</strong>. Version 1.0.3 <a href="https://github.com/oven-sh/bun/releases" target="_blank" rel="noreferrer noopener">has just been released</a>, and you can already use it for your projects hosted by Clever Cloud.</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>While we like to automate and simplify everything for our customers, we do so while leaving as much freedom as possible. Thus, hosting <a href="https://stagingv6.cleverapps.io/product/node-js-applications/">a Node.js application</a> with the framework or package manager of your choice can be done without any particular constraints, and deploying a website takes only a few minutes.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>We already support <a href="https://stagingv6.cleverapps.io/blog/engineering/2020/05/19/deploy-deno/">Deno</a>, <a href="https://stagingv6.cleverapps.io/doc/deploy/application/javascript/by-framework/meteor/">Meteor.js</a>, <a href="https://stagingv6.cleverapps.io/doc/deploy/application/javascript/by-framework/nodejs/#supported-package-managers">yarn</a>. While we haven't yet taken the decision to integrate Bun natively into our images, as we await initial feedback from our customers, it's all very straightforward.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">Hello, Bun on Clever Cloud!</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Want to give it a try? All you need is a Clever Cloud account, or create one from an e-mail address or GitHub account. We'll give you 20 euros worth of credits when you sign up.</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><!-- wp:list-item -->
<li><a href="https://api.clever-cloud.com/v2/session/signup">Create a Clever Cloud account</a> (and get 20 euros in credits)</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>For this first example, we'll assume that you have a machine running <a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git" target="_blank" rel="noreferrer noopener">git</a> and a recent version of <a href="https://nodejs.dev/en/learn/how-to-install-nodejs/" target="_blank" rel="noreferrer noopener">Node.js</a>. If you haven't yet installed our open source <a href="https://github.com/CleverCloud/clever-tools" target="_blank" rel="noreferrer noopener">Clever Tools</a> command line interface (CLI), type (with administrator rights on your system or <code>sudo</code> if necessary) :</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">npm i -g clever-tools
clever login</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>Once logged in, you can check that everything has gone correctly with the following command:</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">clever profile</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>Let's install Bun and create our first application:</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">npm install -g bun
mkdir clevbun &amp;&amp; cd clevbun<br>bun init -y &amp;&amp; git init</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>This will create a local git repository and a whole series of files, including <code>package.json</code> which contains your project's configuration. But also <code>index.ts</code> and <code>ts.config.json</code>, which are specific to the TypeScript language used by Bun by default. Don't worry, it handles simple JavaScript files just as well as <a href="https://bun.sh/docs/runtime/jsx" target="_blank" rel="noreferrer noopener">JSX/TSX</a>, ECMAScript and CommonJS modules, which are imported <a href="https://bun.sh/docs/runtime/modules" target="_blank" rel="noreferrer noopener">in a unified way</a>, <a href="https://bun.sh/docs/api/ffi" target="_blank" rel="noreferrer noopener">low-level languages</a> or <a href="https://bun.sh/docs/api/sqlite" target="_blank" rel="noreferrer noopener">SQLite</a>. That's one of its strengths.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Let's check that everything worked as planned:</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">&gt; bun index.ts
Hello via Bun!</code></pre>
<!-- /wp:html -->

<!-- wp:heading -->
<h2 class="wp-block-heading">An application using Bun's HTTP server</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Our aim is to host a web application, so we're going to use an HTTP server. It's a good thing that Bun has its own, in addition to ensuring compatibility with Node.js functionalities and APIs. Developed using the <a href="https://fr.wikipedia.org/wiki/Zig_(langage)" target="_blank" rel="noreferrer noopener">Zig language</a>, using the <a href="https://fr.wikipedia.org/wiki/JavaScriptCore" target="_blank" rel="noreferrer noopener">JavaScriptCore</a> engine rather than v8, this runtime claims to be much more efficient for such uses.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Modify the contents of the <code>index.ts</code> file as follows:</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">Bun.serve({
  port: 8080,
  hostname: '0.0.0.0',
  fetch(req) {
    const url = new URL(req.url);
    if (url.pathname === "/") return new Response("Home page!");
    if (url.pathname === "/blog") return new Response("Blog!");
    return new Response("404!");
  },
  error(error) {
    return new Response(`&lt;pre&gt;${error}\n${error.stack}&lt;/pre&gt;`, {
      headers: {
        "Content-Type": "text/html",
      },
    });
  },
});</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>This creates an HTTP server that sends a different response depending on the route (<code>url.pathname</code>) and a 404 error if none matches. If a problem occurs, a dedicated page will be displayed. Note that port 8080 is here specified in the code, but it could be defined with an environment variable: <code>$PORT</code>, <code>$BUN_PORT</code> or <code>$NODE_PORT</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">Clever deploy!</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Now let's get down to the nitty-gritty of deploying on Clever Cloud, starting by preparing the application:</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">clever create -t node clevbun
clever env set CC_PRE_BUILD_HOOK "npm i -g bun"
clever env set CC_NODE_BUILD_TOOL "custom"
clever env set CC_CUSTOM_BUILD_TOOL "bun install"
clever env set CC_RUN_COMMAND "bun run index.ts"</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>The first command creates the application within your Clever Cloud account. Then we define environment variables for installing Bun within the image, followed by instructions for configuring dependencies and launching the project. As with Node.js, you can specify that an application is ready for production by assigning the value <code>production</code> to the <code>NODE_ENV</code> environment variable.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>It is then available from our infrastructure and opened in your browser. Note that you can use this configuration to use Bun on a Node.js application already hosted by Clever Cloud by adapting <code>CC_RUN_COMMAND</code> to your project.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Now that our application has been created, it can be deployed. It's as simple as a <code>git push</code>!</p>
<!-- /wp:paragraph -->

<!-- wp:code {"className":"language-bash"} -->
<pre class="wp-block-code language-bash"><code>git add . &amp;&amp; git commit -m "First commit"
clever deploy &amp;&amp; clever open</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>This should deploy the application on our infrastructure and open it in your browser. You can add <code>/blog</code> or <code>/random</code> at the end of the URL to check that routing works properly. </p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">Many possibilities</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>You don't have to worry about configuring HTTPS access, log collection or metrics - everything is already set up, accessible through Clever Tools or <a href="https://console.clever-cloud.com/">the Console</a>. You can also use the latter to activate <a href="https://stagingv6.cleverapps.io/fr/blog/features/2021/10/28/grafana-pour-des-metriques-d-applications/">Grafana</a> in your account settings. </p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">clever console</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>Other Clever Tools features let you assign it a domain, view its parameters and activity, modify the number and type of instances used, and stop or restart it. Take a look at our CLI help with <code>--help</code> or <a href="https://github.com/CleverCloud/clever-tools/tree/master#how-to-use" target="_blank" rel="noreferrer noopener">its documentation</a> to find out more:</p>
<!-- /wp:paragraph -->

<!-- wp:code {"className":"language-bash"} -->
<pre class="wp-block-code language-bash"><code>clever domain
clever domain add domain.tld

clever status
clever activity

clever scale --min-instances 1 --max-instances 4 --min-flavor pico --max-flavor M
clever scale --instances 1 --flavor pico

clever restart
clever stop</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Of course, you can also go further with Bun and deploy applications using <a href="https://twitter.com/davlgd/status/1700478826755530822" target="_blank" rel="noreferrer noopener">the Elysia web framework</a> or static site generators <a href="https://twitter.com/davlgd/status/1700599956359262313" target="_blank" rel="noreferrer noopener">such as Astro</a>. We'll tell you all about that in future blog posts! Meanwhile, let us know what you expect from our JavaScript runtime images.</p>
<!-- /wp:paragraph -->]]></description>
										<content:encoded><![CDATA[<p><img width="1480" height="740" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2023/09/banner-bun-on-clever-cloud.svg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="BANNIER bun" decoding="async" /></p><!-- wp:paragraph -->
<p><strong>For more than a year now, Jarred Sumner and his team have been working on a new open source JavaScript runtime: <a href="https://github.com/oven-sh/bun" target="_blank" rel="noreferrer noopener">Bun</a>. <strong> It's touted as more efficient and feature-rich than current solutions such as Node.js or Deno</strong>. Version 1.0.3 <a href="https://github.com/oven-sh/bun/releases" target="_blank" rel="noreferrer noopener">has just been released</a>, and you can already use it for your projects hosted by Clever Cloud.</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>While we like to automate and simplify everything for our customers, we do so while leaving as much freedom as possible. Thus, hosting <a href="https://stagingv6.cleverapps.io/product/node-js-applications/">a Node.js application</a> with the framework or package manager of your choice can be done without any particular constraints, and deploying a website takes only a few minutes.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>We already support <a href="https://stagingv6.cleverapps.io/blog/engineering/2020/05/19/deploy-deno/">Deno</a>, <a href="https://stagingv6.cleverapps.io/doc/deploy/application/javascript/by-framework/meteor/">Meteor.js</a>, <a href="https://stagingv6.cleverapps.io/doc/deploy/application/javascript/by-framework/nodejs/#supported-package-managers">yarn</a>. While we haven't yet taken the decision to integrate Bun natively into our images, as we await initial feedback from our customers, it's all very straightforward.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">Hello, Bun on Clever Cloud!</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Want to give it a try? All you need is a Clever Cloud account, or create one from an e-mail address or GitHub account. We'll give you 20 euros worth of credits when you sign up.</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><!-- wp:list-item -->
<li><a href="https://api.clever-cloud.com/v2/session/signup">Create a Clever Cloud account</a> (and get 20 euros in credits)</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>For this first example, we'll assume that you have a machine running <a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git" target="_blank" rel="noreferrer noopener">git</a> and a recent version of <a href="https://nodejs.dev/en/learn/how-to-install-nodejs/" target="_blank" rel="noreferrer noopener">Node.js</a>. If you haven't yet installed our open source <a href="https://github.com/CleverCloud/clever-tools" target="_blank" rel="noreferrer noopener">Clever Tools</a> command line interface (CLI), type (with administrator rights on your system or <code>sudo</code> if necessary) :</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">npm i -g clever-tools
clever login</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>Once logged in, you can check that everything has gone correctly with the following command:</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">clever profile</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>Let's install Bun and create our first application:</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">npm install -g bun
mkdir clevbun &amp;&amp; cd clevbun<br>bun init -y &amp;&amp; git init</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>This will create a local git repository and a whole series of files, including <code>package.json</code> which contains your project's configuration. But also <code>index.ts</code> and <code>ts.config.json</code>, which are specific to the TypeScript language used by Bun by default. Don't worry, it handles simple JavaScript files just as well as <a href="https://bun.sh/docs/runtime/jsx" target="_blank" rel="noreferrer noopener">JSX/TSX</a>, ECMAScript and CommonJS modules, which are imported <a href="https://bun.sh/docs/runtime/modules" target="_blank" rel="noreferrer noopener">in a unified way</a>, <a href="https://bun.sh/docs/api/ffi" target="_blank" rel="noreferrer noopener">low-level languages</a> or <a href="https://bun.sh/docs/api/sqlite" target="_blank" rel="noreferrer noopener">SQLite</a>. That's one of its strengths.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Let's check that everything worked as planned:</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">&gt; bun index.ts
Hello via Bun!</code></pre>
<!-- /wp:html -->

<!-- wp:heading -->
<h2 class="wp-block-heading">An application using Bun's HTTP server</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Our aim is to host a web application, so we're going to use an HTTP server. It's a good thing that Bun has its own, in addition to ensuring compatibility with Node.js functionalities and APIs. Developed using the <a href="https://fr.wikipedia.org/wiki/Zig_(langage)" target="_blank" rel="noreferrer noopener">Zig language</a>, using the <a href="https://fr.wikipedia.org/wiki/JavaScriptCore" target="_blank" rel="noreferrer noopener">JavaScriptCore</a> engine rather than v8, this runtime claims to be much more efficient for such uses.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Modify the contents of the <code>index.ts</code> file as follows:</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">Bun.serve({
  port: 8080,
  hostname: '0.0.0.0',
  fetch(req) {
    const url = new URL(req.url);
    if (url.pathname === "/") return new Response("Home page!");
    if (url.pathname === "/blog") return new Response("Blog!");
    return new Response("404!");
  },
  error(error) {
    return new Response(`&lt;pre&gt;${error}\n${error.stack}&lt;/pre&gt;`, {
      headers: {
        "Content-Type": "text/html",
      },
    });
  },
});</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>This creates an HTTP server that sends a different response depending on the route (<code>url.pathname</code>) and a 404 error if none matches. If a problem occurs, a dedicated page will be displayed. Note that port 8080 is here specified in the code, but it could be defined with an environment variable: <code>$PORT</code>, <code>$BUN_PORT</code> or <code>$NODE_PORT</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">Clever deploy!</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Now let's get down to the nitty-gritty of deploying on Clever Cloud, starting by preparing the application:</p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">clever create -t node clevbun
clever env set CC_PRE_BUILD_HOOK "npm i -g bun"
clever env set CC_NODE_BUILD_TOOL "custom"
clever env set CC_CUSTOM_BUILD_TOOL "bun install"
clever env set CC_RUN_COMMAND "bun run index.ts"</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>The first command creates the application within your Clever Cloud account. Then we define environment variables for installing Bun within the image, followed by instructions for configuring dependencies and launching the project. As with Node.js, you can specify that an application is ready for production by assigning the value <code>production</code> to the <code>NODE_ENV</code> environment variable.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>It is then available from our infrastructure and opened in your browser. Note that you can use this configuration to use Bun on a Node.js application already hosted by Clever Cloud by adapting <code>CC_RUN_COMMAND</code> to your project.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Now that our application has been created, it can be deployed. It's as simple as a <code>git push</code>!</p>
<!-- /wp:paragraph -->

<!-- wp:code {"className":"language-bash"} -->
<pre class="wp-block-code language-bash"><code>git add . &amp;&amp; git commit -m "First commit"
clever deploy &amp;&amp; clever open</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>This should deploy the application on our infrastructure and open it in your browser. You can add <code>/blog</code> or <code>/random</code> at the end of the URL to check that routing works properly. </p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">Many possibilities</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>You don't have to worry about configuring HTTPS access, log collection or metrics - everything is already set up, accessible through Clever Tools or <a href="https://console.clever-cloud.com/">the Console</a>. You can also use the latter to activate <a href="https://stagingv6.cleverapps.io/fr/blog/features/2021/10/28/grafana-pour-des-metriques-d-applications/">Grafana</a> in your account settings. </p>
<!-- /wp:paragraph -->

<!-- wp:html -->
<pre class="wp-block-code"><code class="language-bash">clever console</code></pre>
<!-- /wp:html -->

<!-- wp:paragraph -->
<p>Other Clever Tools features let you assign it a domain, view its parameters and activity, modify the number and type of instances used, and stop or restart it. Take a look at our CLI help with <code>--help</code> or <a href="https://github.com/CleverCloud/clever-tools/tree/master#how-to-use" target="_blank" rel="noreferrer noopener">its documentation</a> to find out more:</p>
<!-- /wp:paragraph -->

<!-- wp:code {"className":"language-bash"} -->
<pre class="wp-block-code language-bash"><code>clever domain
clever domain add domain.tld

clever status
clever activity

clever scale --min-instances 1 --max-instances 4 --min-flavor pico --max-flavor M
clever scale --instances 1 --flavor pico

clever restart
clever stop</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Of course, you can also go further with Bun and deploy applications using <a href="https://twitter.com/davlgd/status/1700478826755530822" target="_blank" rel="noreferrer noopener">the Elysia web framework</a> or static site generators <a href="https://twitter.com/davlgd/status/1700599956359262313" target="_blank" rel="noreferrer noopener">such as Astro</a>. We'll tell you all about that in future blog posts! Meanwhile, let us know what you expect from our JavaScript runtime images.</p>
<!-- /wp:paragraph -->]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using JAAS in the Cloud Era</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2020/09/09/using-jaas-in-the-cloud-era/</link>
		
		<dc:creator><![CDATA[Julien Durillon]]></dc:creator>
		<pubDate>Wed, 09 Sep 2020 15:44:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Developers]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/09/09/using-jaas-in-the-cloud-era/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>In this article, we will learn how to configure JAAS authentication in a JVM application without resorting to configuration files. This is motivated by the fact that, in a cloud setup, persisting a configuration file to an ephemeral instance/container is not a good practice.</p>
<span id="more-2831"></span>

<h2 id="the-problem">The problem</h2>
<p>You are writing an application that depends on a <a href="https://zookeeper.apache.org/">ZooKeeper</a> cluster. The moment comes when you need to put your code into production. During the early development of your application you were running a ZooKeeper instance on your laptop. Now that you are deploying to production, you need a secure connection between your app and the production ZooKeeper cluster you just set up.</p>
<p>Reading the <a href="https://zookeeper.apache.org/doc/r3.6.1/zookeeperAdmin.html#sc_authOptions" title="ZooKeeper authentication options">ZooKeeper documentation</a> you learn that you can achieve that through multiple ways: X509, SASL Kerberos, SASL Digest. Since you just want to demonstrate your POC, you have no wish to take on the burden of using X509 client certificates or to deploy a Kerberos architecture. So you fallback to SASL Digest. It&#39;s simple and easy, it&#39;s a user/password pair like you are used to.</p>
<p>Reading <a href="https://cwiki.apache.org/confluence/display/ZOOKEEPER/Client-Server+mutual+authentication#ClientServermutualauthentication-ClientConfiguration" title="ZK Auth">some more documentation</a> you learn that you have to put the credentials in a jaas.conf file. You then look into <em>the internet</em> to find a way to bypass this requirement.</p>
<p>Well, your search is over, your quest ends with this very article!</p>
<p>You just want to copy some code and don&#39;t care about the whole &quot;let&#39;s talk about X&quot; part? Jump to the <a href="#how-to-get-rid-of-jaas-config-file">&quot;How to get rid of jaas.config file&quot;</a> section!</p>
<h2 id="some-explanations-first">Some explanations first</h2>
<p>Since Java 1.4, a security framework has been added to the JRE: the <a href="https://docs.oracle.com/en/java/javase/14/security/java-authentication-and-authorization-service-jaas-reference-guide.html#GUID-FA47090A-D270-4E4E-A5F6-752E1A48DC4C" title="JAAS Official doc">Java Authentication and Authorization Service (JAAS)</a>.</p>
<p>JAAS is a quite comprehensive and pluggable framework. The only downside is that it&#39;s thought as a service meant to authenticate &quot;the user running the code&quot;. So it has a tendency to use configuration files or even system JVM configuration.</p>
<p>Configuration based on files containing secrets is a growing no-go in the cloud era. Since most clouds rely on disposable systems, using a JAAS file means one of the following:</p>
<ol>
<li>commiting the file, with the secrets in it;</li>
<li>commiting a file and use pre-run hooks to set the right value in it;</li>
<li>running an external service that would provide this file.</li>
</ol>
<p>Solution 1 is a strict no-go. Solution 2 is doable, but as a developer, I don&#39;t like having to resort to such practices. However, it&#39;s still better than solution 1, I&#39;m just stating my very personal point on view! Solution 3 is a bit like solution 2. It needs some kind of pre-run hook. In addition, it needs to trust the external source.</p>
<p>In this article, we will see how to abstract ourselves from the file-based JAAS login configuration. I will use a ZooKeeper Java/Scala client as an example.</p>
<h2 id="whats-in-the-box-jaas-file">What&#39;s in the <del>box</del> JAAS file?</h2>
<p>First, what is a JAAS file made of?</p>
<p>As the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/LoginConfigFile.html">Oracle documentation</a> states, it is made of <em>entries</em>. Each <em>entry</em> is composed of multiple <em>modules</em>. Each <em>module</em> provides a login/authorization mechanism with all its options. An authentication/authorization process has to satisfy all <em>modules</em> of the <em>entry</em> to succeed.</p>
<h3 id="example">Example</h3>
<p>We assume that the server part is already configured. Here we focus on the client part only.</p>
<p>Let&#39;s say we want to authenticate a Java application against a ZooKeeper cluster using the DIGEST-MD5 <a href="https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer" title="Wikipedia SASL">SASL</a> mechanism. We write a jaas.conf file somewhere on the filesystem. Here is what the file content will look like:</p>
<pre><code class="language-text">Client {
   org.apache.zookeeper.server.auth.DigestLoginModule required
   username=&quot;buffysummers&quot;
   password=&quot;vampiresbeware&quot;;
};
</code></pre>
<p>The <em>entry</em> name is <code>Client</code> (the default client session name for ZooKeeper). There is one module identified by the FQDN of the <code>LoginModule</code> class that will process the authentication/authorization. This module is <code>required</code> and has two parameters: <code>username</code> and <code>password</code>. No spaces around the <code>=</code>, the semicolon separates the modules. So only one is needed at the end of the module. One is also needed after the entry.</p>
<p>&quot;Executing&quot; this entry is quite straightforward: Java instanciates the <code>org.apache.zookeeper.server.auth.DigestLoginModule</code> class and calls <code>initialize(&quot;subject&quot;, callback, sharedState, Map(username=buffysummers, password=vampirebeware))</code> on the instance. After that, the actual client will use the instance&#39;s methods to perform authentication/authorization.</p>
<p>It&#39;s the developer&#39;s responsibility to ensure the module class is present in the classpath. In the case of ZooKeeper, the library provides the <code>org.apache.zookeeper.server.auth.DigestLoginModule</code> class.</p>
<p>Oh, one last thing about the JAAS file syntax: for each <em>module</em> you must say if the module is required, sufficient, optional, etc. That&#39;s what the <code>required</code> keyword is about! That way you can require multiple authentication methods to pass or you can just ask for one of them to pass.</p>
<h3 id="how-does-it-work-in-the-jvm">How does it work in the JVM?</h3>
<p>When running your application, the client code will use the <code>javax.security.auth.login.Configuration</code> static class to access your configured JAAS. Actually, it will use the only JRE provided implementation <code>com.sun.security.auth.login.ConfigFile</code>, which parses your provided jaas.conf file.</p>
<p>The Configuration singleton provides one method, <code>getAppConfigurationEntry(String entryName)</code>. In our example, by default, the ZooKeeper client calls the method with the string &quot;Client&quot;.</p>
<p>In most JREs, there is no default JAAS file. That means <code>Configuration</code> has no entries.</p>
<h3 id="how-do-i-tell-the-jvm-where-to-find-jaasconf">How do I tell the JVM where to find jaas.conf?</h3>
<p>According to <a href="https://docs.oracle.com/en/java/javase/14/docs/api/jdk.security.auth/com/sun/security/auth/login/ConfigFile.html" title="Javadoc ConfigFile">the javadoc</a>, there are multiple ways to do that:</p>
<ul>
<li>edit the java.security system file (in <code>$JAVA_HOME</code>);</li>
<li>run your app with the java option <code>-Djava.security.auth.login.config=path/to/jaas.conf</code>;</li>
<li>put the file in the default location: <code>$HOME/.java.login.config</code>.</li>
</ul>
<p>The next section will show us how to setup your JVM using Java code, without relying on the filesystem. It will keep on using the ZooKeeper client example.</p>
<h2 id="how-to-get-rid-of-jaasconfig-file">How to get rid of jaas.config file</h2>
<p>The answer to that is quite simple: override Java&#39;s Configuration default implementation!</p>
<h3 id="disclaimer">Disclaimer</h3>
<p>Before we dive in the details, please note that <strong>There is only one Configuration object installed in the runtime at any given time</strong>. When we override it, we remove all previous login configurations. Most JREs do not have any default configuration, so you should be safe. However, if you deploy your application in your company&#39;s VMs or container, they may already have specific configuration. So ask around!</p>
<h3 id="implementing-a-new-configuration">Implementing a new Configuration</h3>
<p>First, we define a class that implements javax.security.auth.login.Configuration:</p>
<pre><code class="language-java">import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import java.util.HashMap;
import java.util.Map;

public class MyConfiguration extends Configuration {
   AppConfigurationEntry[] getAppConfigurationEntry(s: String) {
      Map&lt;String,String&gt; options = new HashMap&lt;&gt;();
      options.put(&quot;username&quot;, &quot;buffysummers&quot;);
      options.put(&quot;password&quot;, &quot;vampiresbeware&quot;);

      return {
         new AppConfigurationEntry(
               &quot;org.apache.zookeeper.server.auth.DigestLoginModule&quot;,
               AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
               options
               )
      };
   }
}
</code></pre>
<p>Of course, you are highly encouraged to get the values for <code>username</code> and <code>password</code> from the environment, from a config database, or whatever you want! You might even add a constructor and feed it the credentials. You do you!</p>
<p>The next step is to instanciate it. You need to do it before you create a new ZooKeeper client instance:</p>
<pre><code class="language-java">// 1. Do that somewhere *before* creating the ZooKeeper instance.
// I would say do it close enough so other people can understand why you do it, or
// document this call because it is kind of cryptic.
Configuration.setConfiguration(new MyConfiguration());

// 2. Just create the zookeeper instance as usual!
ZooKeeper zookeeper = new ZooKeeper(&quot;localhost:2181&quot;, 3600000, watchCallback);

// 3. ?

// 4. PROFIT!
</code></pre>
<p>And that&#39;s it.</p>
<h2 id="alternative-method">Alternative method</h2>
<p>When writing this article, I read the documentation a bit more in depth and found out that I could use Java properties in the JAAS configuration file!</p>
<p>So instead of the code-only solution, we could actually just commit a jaas.conf file containing:</p>
<pre><code class="language-text">Client {
   org.apache.zookeeper.server.auth.DigestLoginModule required
   username=&quot;${app.zookeeper.username}&quot;
   password=&quot;${app.zookeeper.password}&quot;;
};
</code></pre>
<p>Then run your Java application with the Java options: <code>-Dapp.zookeeper.username=buffysummers</code> and <code>-Dapp.zookeeper.password=vampirebeware</code>.</p>
<p>I tried it, it works!</p>
<p>Depending on your application, using this solution might be easier than the full-code one.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Now that we understand a bit more about JAAS and how to avoid using the file format, there is actually only one advice to keep in mind: <strong>DO NOT STORE CREDENTIALS IN YOUR GIT REPOSITORY!</strong> By using one of the two proposed solutions, you should be able to have the secrets provided by the environment.</p>
<p>Besides, both of them should work on Clever Cloud. Your environment variables are injected in your application both as environement and as Java properties! You can also define a variable named <code>app.zookeeper.username</code>. It will only appear as a Java property, due to limitations in environment variables names.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/jaas-cloud-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>In this article, we will learn how to configure JAAS authentication in a JVM application without resorting to configuration files. This is motivated by the fact that, in a cloud setup, persisting a configuration file to an ephemeral instance/container is not a good practice.</p>
<span id="more-2831"></span>

<h2 id="the-problem">The problem</h2>
<p>You are writing an application that depends on a <a href="https://zookeeper.apache.org/">ZooKeeper</a> cluster. The moment comes when you need to put your code into production. During the early development of your application you were running a ZooKeeper instance on your laptop. Now that you are deploying to production, you need a secure connection between your app and the production ZooKeeper cluster you just set up.</p>
<p>Reading the <a href="https://zookeeper.apache.org/doc/r3.6.1/zookeeperAdmin.html#sc_authOptions" title="ZooKeeper authentication options">ZooKeeper documentation</a> you learn that you can achieve that through multiple ways: X509, SASL Kerberos, SASL Digest. Since you just want to demonstrate your POC, you have no wish to take on the burden of using X509 client certificates or to deploy a Kerberos architecture. So you fallback to SASL Digest. It&#39;s simple and easy, it&#39;s a user/password pair like you are used to.</p>
<p>Reading <a href="https://cwiki.apache.org/confluence/display/ZOOKEEPER/Client-Server+mutual+authentication#ClientServermutualauthentication-ClientConfiguration" title="ZK Auth">some more documentation</a> you learn that you have to put the credentials in a jaas.conf file. You then look into <em>the internet</em> to find a way to bypass this requirement.</p>
<p>Well, your search is over, your quest ends with this very article!</p>
<p>You just want to copy some code and don&#39;t care about the whole &quot;let&#39;s talk about X&quot; part? Jump to the <a href="#how-to-get-rid-of-jaas-config-file">&quot;How to get rid of jaas.config file&quot;</a> section!</p>
<h2 id="some-explanations-first">Some explanations first</h2>
<p>Since Java 1.4, a security framework has been added to the JRE: the <a href="https://docs.oracle.com/en/java/javase/14/security/java-authentication-and-authorization-service-jaas-reference-guide.html#GUID-FA47090A-D270-4E4E-A5F6-752E1A48DC4C" title="JAAS Official doc">Java Authentication and Authorization Service (JAAS)</a>.</p>
<p>JAAS is a quite comprehensive and pluggable framework. The only downside is that it&#39;s thought as a service meant to authenticate &quot;the user running the code&quot;. So it has a tendency to use configuration files or even system JVM configuration.</p>
<p>Configuration based on files containing secrets is a growing no-go in the cloud era. Since most clouds rely on disposable systems, using a JAAS file means one of the following:</p>
<ol>
<li>commiting the file, with the secrets in it;</li>
<li>commiting a file and use pre-run hooks to set the right value in it;</li>
<li>running an external service that would provide this file.</li>
</ol>
<p>Solution 1 is a strict no-go. Solution 2 is doable, but as a developer, I don&#39;t like having to resort to such practices. However, it&#39;s still better than solution 1, I&#39;m just stating my very personal point on view! Solution 3 is a bit like solution 2. It needs some kind of pre-run hook. In addition, it needs to trust the external source.</p>
<p>In this article, we will see how to abstract ourselves from the file-based JAAS login configuration. I will use a ZooKeeper Java/Scala client as an example.</p>
<h2 id="whats-in-the-box-jaas-file">What&#39;s in the <del>box</del> JAAS file?</h2>
<p>First, what is a JAAS file made of?</p>
<p>As the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/LoginConfigFile.html">Oracle documentation</a> states, it is made of <em>entries</em>. Each <em>entry</em> is composed of multiple <em>modules</em>. Each <em>module</em> provides a login/authorization mechanism with all its options. An authentication/authorization process has to satisfy all <em>modules</em> of the <em>entry</em> to succeed.</p>
<h3 id="example">Example</h3>
<p>We assume that the server part is already configured. Here we focus on the client part only.</p>
<p>Let&#39;s say we want to authenticate a Java application against a ZooKeeper cluster using the DIGEST-MD5 <a href="https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer" title="Wikipedia SASL">SASL</a> mechanism. We write a jaas.conf file somewhere on the filesystem. Here is what the file content will look like:</p>
<pre><code class="language-text">Client {
   org.apache.zookeeper.server.auth.DigestLoginModule required
   username=&quot;buffysummers&quot;
   password=&quot;vampiresbeware&quot;;
};
</code></pre>
<p>The <em>entry</em> name is <code>Client</code> (the default client session name for ZooKeeper). There is one module identified by the FQDN of the <code>LoginModule</code> class that will process the authentication/authorization. This module is <code>required</code> and has two parameters: <code>username</code> and <code>password</code>. No spaces around the <code>=</code>, the semicolon separates the modules. So only one is needed at the end of the module. One is also needed after the entry.</p>
<p>&quot;Executing&quot; this entry is quite straightforward: Java instanciates the <code>org.apache.zookeeper.server.auth.DigestLoginModule</code> class and calls <code>initialize(&quot;subject&quot;, callback, sharedState, Map(username=buffysummers, password=vampirebeware))</code> on the instance. After that, the actual client will use the instance&#39;s methods to perform authentication/authorization.</p>
<p>It&#39;s the developer&#39;s responsibility to ensure the module class is present in the classpath. In the case of ZooKeeper, the library provides the <code>org.apache.zookeeper.server.auth.DigestLoginModule</code> class.</p>
<p>Oh, one last thing about the JAAS file syntax: for each <em>module</em> you must say if the module is required, sufficient, optional, etc. That&#39;s what the <code>required</code> keyword is about! That way you can require multiple authentication methods to pass or you can just ask for one of them to pass.</p>
<h3 id="how-does-it-work-in-the-jvm">How does it work in the JVM?</h3>
<p>When running your application, the client code will use the <code>javax.security.auth.login.Configuration</code> static class to access your configured JAAS. Actually, it will use the only JRE provided implementation <code>com.sun.security.auth.login.ConfigFile</code>, which parses your provided jaas.conf file.</p>
<p>The Configuration singleton provides one method, <code>getAppConfigurationEntry(String entryName)</code>. In our example, by default, the ZooKeeper client calls the method with the string &quot;Client&quot;.</p>
<p>In most JREs, there is no default JAAS file. That means <code>Configuration</code> has no entries.</p>
<h3 id="how-do-i-tell-the-jvm-where-to-find-jaasconf">How do I tell the JVM where to find jaas.conf?</h3>
<p>According to <a href="https://docs.oracle.com/en/java/javase/14/docs/api/jdk.security.auth/com/sun/security/auth/login/ConfigFile.html" title="Javadoc ConfigFile">the javadoc</a>, there are multiple ways to do that:</p>
<ul>
<li>edit the java.security system file (in <code>$JAVA_HOME</code>);</li>
<li>run your app with the java option <code>-Djava.security.auth.login.config=path/to/jaas.conf</code>;</li>
<li>put the file in the default location: <code>$HOME/.java.login.config</code>.</li>
</ul>
<p>The next section will show us how to setup your JVM using Java code, without relying on the filesystem. It will keep on using the ZooKeeper client example.</p>
<h2 id="how-to-get-rid-of-jaasconfig-file">How to get rid of jaas.config file</h2>
<p>The answer to that is quite simple: override Java&#39;s Configuration default implementation!</p>
<h3 id="disclaimer">Disclaimer</h3>
<p>Before we dive in the details, please note that <strong>There is only one Configuration object installed in the runtime at any given time</strong>. When we override it, we remove all previous login configurations. Most JREs do not have any default configuration, so you should be safe. However, if you deploy your application in your company&#39;s VMs or container, they may already have specific configuration. So ask around!</p>
<h3 id="implementing-a-new-configuration">Implementing a new Configuration</h3>
<p>First, we define a class that implements javax.security.auth.login.Configuration:</p>
<pre><code class="language-java">import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import java.util.HashMap;
import java.util.Map;

public class MyConfiguration extends Configuration {
   AppConfigurationEntry[] getAppConfigurationEntry(s: String) {
      Map&lt;String,String&gt; options = new HashMap&lt;&gt;();
      options.put(&quot;username&quot;, &quot;buffysummers&quot;);
      options.put(&quot;password&quot;, &quot;vampiresbeware&quot;);

      return {
         new AppConfigurationEntry(
               &quot;org.apache.zookeeper.server.auth.DigestLoginModule&quot;,
               AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
               options
               )
      };
   }
}
</code></pre>
<p>Of course, you are highly encouraged to get the values for <code>username</code> and <code>password</code> from the environment, from a config database, or whatever you want! You might even add a constructor and feed it the credentials. You do you!</p>
<p>The next step is to instanciate it. You need to do it before you create a new ZooKeeper client instance:</p>
<pre><code class="language-java">// 1. Do that somewhere *before* creating the ZooKeeper instance.
// I would say do it close enough so other people can understand why you do it, or
// document this call because it is kind of cryptic.
Configuration.setConfiguration(new MyConfiguration());

// 2. Just create the zookeeper instance as usual!
ZooKeeper zookeeper = new ZooKeeper(&quot;localhost:2181&quot;, 3600000, watchCallback);

// 3. ?

// 4. PROFIT!
</code></pre>
<p>And that&#39;s it.</p>
<h2 id="alternative-method">Alternative method</h2>
<p>When writing this article, I read the documentation a bit more in depth and found out that I could use Java properties in the JAAS configuration file!</p>
<p>So instead of the code-only solution, we could actually just commit a jaas.conf file containing:</p>
<pre><code class="language-text">Client {
   org.apache.zookeeper.server.auth.DigestLoginModule required
   username=&quot;${app.zookeeper.username}&quot;
   password=&quot;${app.zookeeper.password}&quot;;
};
</code></pre>
<p>Then run your Java application with the Java options: <code>-Dapp.zookeeper.username=buffysummers</code> and <code>-Dapp.zookeeper.password=vampirebeware</code>.</p>
<p>I tried it, it works!</p>
<p>Depending on your application, using this solution might be easier than the full-code one.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Now that we understand a bit more about JAAS and how to avoid using the file format, there is actually only one advice to keep in mind: <strong>DO NOT STORE CREDENTIALS IN YOUR GIT REPOSITORY!</strong> By using one of the two proposed solutions, you should be able to have the secrets provided by the environment.</p>
<p>Besides, both of them should work on Clever Cloud. Your environment variables are injected in your application both as environement and as Java properties! You can also define a variable named <code>app.zookeeper.username</code>. It will only appear as a Java property, due to limitations in environment variables names.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Intro to Clever Cloud-Driven Development</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2016/10/12/clever-cloud-driven-developement/</link>
		
		<dc:creator><![CDATA[Clément Nivolle]]></dc:creator>
		<pubDate>Wed, 12 Oct 2016 16:56:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[Developers]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[workflow]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2016/10/12/clever-cloud-driven-developement/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>In ancient times, developers weren&#39;t able to be just developers. They had to be experts in computer networking and development platforms as well.</p>
<span id="more-2807"></span>

<p>Great ideas had to sit on the sidelines and wait. You had to build out a sandbox to play in before you started coding. If you wanted to use Ruby (on or off Rails), you had to start with something like Ruby Version Manager (RVM) to set up the server space you needed. If you decided that Node.JS was a better fit for your next application, you would have to tear it all down and go get Node Version Manager (NVM) from GitHub. Obviously, people couldn&#39;t live that way for long.</p>
<h2 id="the-dawn-of-reason">The Dawn of Reason</h2>
<p>Platform as a Service (PaaS) providers started popping up about a decade ago and civilization took off from there. Now developers worry about development and the host manages the OS, the software stack, the runtime, the servers, virtualization and storage. That problem then became that PaaS providers were too narrow in their focus.</p>
<p>That&#39;s when Clever Cloud Driven Development (CCDD) was born. It evolved the concept of PaaS and made it polyglot. That means that now you have the freedom to work in any of your preferred runtimes (Docker, PHP, Scala, etc.) and have access to your favorite services (MongoDB, PostgreSQL, Redis, etc.). Now, instant access to those capabilities can be deployed with a simple git push.</p>
<h2 id="tell-me-how">Tell Me How</h2>
<p>One of the tricks that do the magic is the <a href="https://github.com/CleverCloud/clever-tools">Clever Tools™</a>, the official and open-source CLI. Installing it allows the rest of us to use Clever Cloud deploying without leaving the terminal. And that&#39;s pretty awesome.</p>
<blockquote>
<p>…deploying without leaving the Terminal.</p>
</blockquote>
<p>Here the quickstart to install and use it without leaving this page: open your term and paste this:</p>
<pre><code class="language-bash"># Do this once, and forget about it
npm install -g clever-tools &amp;&amp; install-clever-completion &amp;&amp; clever login

# Go to your workDir
# For the Terminalesque ones, create your app without touching a mouse
clever create -t node &quot;My Great Application&quot;
clever deploy
## PROFITT
clever open
## Grep logs as in ye olden days
clever logs --before 2016-10-13 | grep &quot;undefined is not a function&quot;
</code></pre>
<h2 id="what-to-do-with-all-the-extra-time">What to Do With All the Extra Time</h2>
<p>CCDD is not merely a convenience. It actually <em>makes the app world a better place</em>™. It allows developers to do a better job at continuous delivery. When you don&#39;t have to set up and maintain your local environment, your time is freed up to create the additional features that customers want or concentrate on performance tuning.</p>
<p>You don&#39;t need to manage your sandboxes for dev and production. CCDD can update your apps in production with no downtime and assure that they will automatically self-heal and redeploy after a crash.</p>
<p>For lean startups and small developer teams, CCDD means scalability from day one. You don&#39;t need to invest in more servers to handle spikes in traffic if you suddenly someone says something nice about you on Hacker News (one can only hope). CCDD scales horizontally and vertically as needed in an instant.</p>
<p>Every developer deserves top-of-the-line security and reactive monitoring. CCDD is built to handle the infrastructure while you handle the accolades.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/ccdd-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>In ancient times, developers weren&#39;t able to be just developers. They had to be experts in computer networking and development platforms as well.</p>
<span id="more-2807"></span>

<p>Great ideas had to sit on the sidelines and wait. You had to build out a sandbox to play in before you started coding. If you wanted to use Ruby (on or off Rails), you had to start with something like Ruby Version Manager (RVM) to set up the server space you needed. If you decided that Node.JS was a better fit for your next application, you would have to tear it all down and go get Node Version Manager (NVM) from GitHub. Obviously, people couldn&#39;t live that way for long.</p>
<h2 id="the-dawn-of-reason">The Dawn of Reason</h2>
<p>Platform as a Service (PaaS) providers started popping up about a decade ago and civilization took off from there. Now developers worry about development and the host manages the OS, the software stack, the runtime, the servers, virtualization and storage. That problem then became that PaaS providers were too narrow in their focus.</p>
<p>That&#39;s when Clever Cloud Driven Development (CCDD) was born. It evolved the concept of PaaS and made it polyglot. That means that now you have the freedom to work in any of your preferred runtimes (Docker, PHP, Scala, etc.) and have access to your favorite services (MongoDB, PostgreSQL, Redis, etc.). Now, instant access to those capabilities can be deployed with a simple git push.</p>
<h2 id="tell-me-how">Tell Me How</h2>
<p>One of the tricks that do the magic is the <a href="https://github.com/CleverCloud/clever-tools">Clever Tools™</a>, the official and open-source CLI. Installing it allows the rest of us to use Clever Cloud deploying without leaving the terminal. And that&#39;s pretty awesome.</p>
<blockquote>
<p>…deploying without leaving the Terminal.</p>
</blockquote>
<p>Here the quickstart to install and use it without leaving this page: open your term and paste this:</p>
<pre><code class="language-bash"># Do this once, and forget about it
npm install -g clever-tools &amp;&amp; install-clever-completion &amp;&amp; clever login

# Go to your workDir
# For the Terminalesque ones, create your app without touching a mouse
clever create -t node &quot;My Great Application&quot;
clever deploy
## PROFITT
clever open
## Grep logs as in ye olden days
clever logs --before 2016-10-13 | grep &quot;undefined is not a function&quot;
</code></pre>
<h2 id="what-to-do-with-all-the-extra-time">What to Do With All the Extra Time</h2>
<p>CCDD is not merely a convenience. It actually <em>makes the app world a better place</em>™. It allows developers to do a better job at continuous delivery. When you don&#39;t have to set up and maintain your local environment, your time is freed up to create the additional features that customers want or concentrate on performance tuning.</p>
<p>You don&#39;t need to manage your sandboxes for dev and production. CCDD can update your apps in production with no downtime and assure that they will automatically self-heal and redeploy after a crash.</p>
<p>For lean startups and small developer teams, CCDD means scalability from day one. You don&#39;t need to invest in more servers to handle spikes in traffic if you suddenly someone says something nice about you on Hacker News (one can only hope). CCDD scales horizontally and vertically as needed in an instant.</p>
<p>Every developer deserves top-of-the-line security and reactive monitoring. CCDD is built to handle the infrastructure while you handle the accolades.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Write a Tutorial and Get Rewarded</title>
		<link>https://stagingv6.cleverapps.io/blog/company/2014/04/25/write-a-tutorial-and-get-rewarded/</link>
		
		<dc:creator><![CDATA[Clément Nivolle]]></dc:creator>
		<pubDate>Fri, 25 Apr 2014 00:00:00 +0000</pubDate>
				<category><![CDATA[Company]]></category>
		<category><![CDATA[Contributing]]></category>
		<category><![CDATA[Developers]]></category>
		<category><![CDATA[Documentation]]></category>
		<category><![CDATA[Tutorials]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2014/04/25/write-a-tutorial-and-get-rewarded/</guid>

					<description><![CDATA[<p><img width="700" height="270" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/openingtutorials.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/openingtutorials.png 700w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/openingtutorials-300x116.png 300w" sizes="auto, (max-width: 700px) 100vw, 700px" /></p>We’ve answered many questions via the support, helping us to complete our <a href="https://stagingv6.cleverapps.io/doc/">documentation</a>. Still, we’d like to have more tutorials and guides. Featuring more tailored content will allow our users to get up to speed quicker. We want tutorials written by the community for the community.

<span id="more-2737"></span>

That's why we give you the opportinity to write your own guide for Clever Cloud. And getting paid for that.

The process is pretty straightforward:
<h4 id="step-1-submit-an-excerpt">Step 1. Submit an Excerpt</h4>
When you have your subject, write a small excerpt, including a four or five-parts breakdown. Submit it to us by opening an issue on our documentation’s Github repository.
<h4 id="step-2-write-and-publish-your-tutorial">Step 2. Write and Publish your Tutorial</h4>
When your excerpt is validated, you can start writing. When it's done, just open a pull request, we will review it.
<h4 id="step-3-profit">Step 3. Profit!</h4>
When the review is done, we will contact you to let you know if it's approved. In that case, you will receive $50 in cash via Paypal or $150 in Clever Cloud credits.

<a class="bt3-btn bt3-btn-success" href="https://github.com/CleverCloud/doc.clever-cloud.com/issues/new" target="_blank" rel="noopener noreferrer">
Start Contributing Now
</a>]]></description>
										<content:encoded><![CDATA[<p><img width="700" height="270" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/openingtutorials.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/openingtutorials.png 700w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/openingtutorials-300x116.png 300w" sizes="auto, (max-width: 700px) 100vw, 700px" /></p>We’ve answered many questions via the support, helping us to complete our <a href="https://stagingv6.cleverapps.io/doc/">documentation</a>. Still, we’d like to have more tutorials and guides. Featuring more tailored content will allow our users to get up to speed quicker. We want tutorials written by the community for the community.

<span id="more-2737"></span>

That's why we give you the opportinity to write your own guide for Clever Cloud. And getting paid for that.

The process is pretty straightforward:
<h4 id="step-1-submit-an-excerpt">Step 1. Submit an Excerpt</h4>
When you have your subject, write a small excerpt, including a four or five-parts breakdown. Submit it to us by opening an issue on our documentation’s Github repository.
<h4 id="step-2-write-and-publish-your-tutorial">Step 2. Write and Publish your Tutorial</h4>
When your excerpt is validated, you can start writing. When it's done, just open a pull request, we will review it.
<h4 id="step-3-profit">Step 3. Profit!</h4>
When the review is done, we will contact you to let you know if it's approved. In that case, you will receive $50 in cash via Paypal or $150 in Clever Cloud credits.

<a class="bt3-btn bt3-btn-success" href="https://github.com/CleverCloud/doc.clever-cloud.com/issues/new" target="_blank" rel="noopener noreferrer">
Start Contributing Now
</a>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Clever Cloud @QCON LONDON</title>
		<link>https://stagingv6.cleverapps.io/blog/company/2013/03/04/qcon-london-2013/</link>
		
		<dc:creator><![CDATA[Adrien Cretté]]></dc:creator>
		<pubDate>Mon, 04 Mar 2013 00:00:00 +0000</pubDate>
				<category><![CDATA[Company]]></category>
		<category><![CDATA[Conference]]></category>
		<category><![CDATA[Developers]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Project management]]></category>
		<category><![CDATA[QCON London]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2013/03/04/qcon-london-2013/</guid>

					<description><![CDATA[French version belowQuentin ADAM, CEO of Clever Cloud, will talk about JavaScript as Data Processing Language &#38; HTML5 Integration at the QCON London next thursday, 7 march. As a reminder, QCON London 2013 will be the 7th edition of this conference designed for developers, team leads, architects and project management. It has already started by [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><em>French version below</em><br />Quentin ADAM, CEO of Clever Cloud, will <a href="http://qconlondon.com/london-2013/presentation/JavaScript%20as%20Data%20Processing%20Language%20&amp;%20HTML5%20Integration">talk about JavaScript as Data Processing Language &amp; HTML5 Integration</a> at the <a href="http://qconlondon.com/london-2013/">QCON London</a> next thursday, 7 march. As a reminder, QCON London 2013 will be the 7th edition of this conference designed for developers, team leads, architects and project management.</p>
<p><span id="more-2711"></span></p>
<p>It has already started by trainings sessions today and tomorrow and the speakers will burst in on the scene next wednesday and thursday.</p>
<p>If you are looking at going to <a href="http://qconlondon.com/london-2013/">QCON London</a>, you can save £100 using the code “ADAM100”.</p>
<p>See ya!</p>
<hr>
<p><em>French version:</em></p>
<h3 id="clever-cloud-à-la-qcon-london">Clever Cloud à la QCON LONDON</h3>
<p>Quentin ADAM, CEO de Clever Cloud, sera à la <a href="http://qconlondon.com/london-2013/">QCON London</a> jeudi prochain, le 7 mars pour parler de <a href="http://qconlondon.com/london-2013/presentation/JavaScript%20as%20Data%20Processing%20Language%20&amp;%20HTML5%20Integration">JavaScript comme langage de traitement de données et d’intégration HTML5</a>. Pour rappel, la QCON London 2013 est la septième édition de cet évènement annuel dédié aux développeurs, à l’architecture logicielle et au management de projet.</p>
<p>L’event a déjà débuté par les séances de trainings aujourd’hui et demain alors que les conférences débuteront à partir de mercredi.</p>
<p>Si vous souhaitez vous y rendre, vous pouvez utiliser le coupon “ADAM100” pour économiser £100 sur le billet d’entrée.</p>
<p>See ya!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Knowing your system &#8211; Part 8 &#8211; On the road to upstream</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2013/02/05/knowing-your-system-part-8-on-the-road-to-upstream/</link>
		
		<dc:creator><![CDATA[Marc-Antoine Perennou]]></dc:creator>
		<pubDate>Tue, 05 Feb 2013 00:00:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Developers]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2013/02/05/knowing-your-system-part-8-on-the-road-to-upstream/</guid>

					<description><![CDATA[How did I start contributing? When I started to really dig into my system to fully understand how it works, breaking everything to know of to fix it, I decided to do even worse and started using scm packages. Scm packages download the source code directly for the upstream development repository using git, subversion, mercurial [&#8230;]]]></description>
										<content:encoded><![CDATA[<h2 id="how-did-i-start-contributing">How did I start contributing?</h2>
<p>When I started to really dig into my system to fully understand how it works, breaking everything to know of to fix it, I decided to do even worse and started using <a href="http://en.wikipedia.org/wiki/Source_Control_Management">scm</a> packages.</p>
<p><span id="more-2791"></span></p>
<p>Scm packages download the source code directly for the upstream development repository using <a href="http://git-scm.com/">git</a>, <a href="http://subversion.tigris.org/">subversion</a>, <a href="http://mercurial.selenic.com/">mercurial</a> or whatever other <a href="http://en.wikipedia.org/wiki/Revision_control">vcs</a>.</p>
<p>Doing this I ended up with a more-that-bleeding-edge system, causing a lot of breakages when stuff went incompatible with recent versions of other. That&#39;s perfect, since that&#39;s exactly the state I wanted to reach. If I wanted to recover a functional system, the easy solution that I adopted when I did not have much spare time was to revert my last changes and get back to an earlier version of the guilty package, but this was not the goal of the operation. What I really started to do at this point was to patch the broken stuff to make it compatible with the newer version of the guilty stuff which broke everything. It was sometimes really trivial, sometimes way less. I mostly did this for <a href="http://www.gnome.org/">Gnome</a> projects. It&#39;s a really good experience since you have to dig in a lot of projects and documentation, making you know better how various parts of your system work internally. Once I had everything back working, I then submitted my patches to the developers of the projects upstream, so that it gets fixed for everyone.</p>
<p>Now that I have way less spare time, I no longer have such a bleeding edge system, or at least I have way less scm packages. Sometimes I still need to patch stuff though, so I still use the same procedure.</p>
<h2 id="my-workflow">My workflow</h2>
<p>My workflow for contributing to upstream is not much different to <a href="http://www.imagination-land.org/posts/2013-01-03-knowing-your-system---part-7---contributing-to-exherbo.html">the one I use for contributing to Exherbo</a>. I also use an autopatch mechanism which is slightly different. My hook for automatically patch software is available there: <a href="https://github.com/Keruspe/paludis-config/blob/exherbo/hooks/ebuild_prepare_pre/patches.bash">https://github.com/Keruspe/paludis-config/blob/exherbo/hooks/ebuild_prepare_pre/patches.bash</a>. If I remember correctly it was initially written by <a href="http://ciaranm.wordpress.com/">Ciaran McCreesh</a>, the <a href="http://paludis.exherbo.org/">paludis</a>&#39;s lead developer. When I want to patch something, I get a copy locally, I write and commit my patch, I generate a patch file and move it to <code>/etc/paludis/autopatch/&lt;category&gt;/&lt;package&gt;/</code> where &lt;category&gt; is for example &quot;x11-dri&quot; and &lt;package&gt; is &quot;mesa&quot;, according to exherbo&#39;s packages name. Each time I install a package, it applies all this patches before configuring and compiling the software. If it works, I submit it upstream, if not, I fix it and retry.</p>
<p>I highly recommend you to try contributing to open source projects, to fix or improve them, like adding new functionalities. The only risk is to learn a lot.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Knowing your system &#8211; Part 2 &#8211; The init process</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2012/11/29/knowing-your-system-part-the-init-process/</link>
		
		<dc:creator><![CDATA[Marc-Antoine Perennou]]></dc:creator>
		<pubDate>Thu, 29 Nov 2012 00:00:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Developers]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2012/11/29/knowing-your-system-part-the-init-process/</guid>

					<description><![CDATA[As we last saw, when we start an UNIX-like system, the kernel gives the hand to a main process called &#8220;init&#8221;. We&#8217;ll now see how it works. The goal of the init process The init process is the most important software running on your system. Its goal is to start everything up in order for [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>As we last saw, when we start an UNIX-like system, the kernel gives the hand to a main process called &#8220;init&#8221;. We&#8217;ll now see how it works.</p>
<p><span id="more-2783"></span></p>
<h2 id="the-goal-of-the-init-process">The goal of the init process</h2>
<p>The init process is the most important software running on your system. Its goal is to start everything up in order for your system to work properly. It will manage everything, report errors (and maybe act regarding them) and supervise everything. When a process gets orphaned (because its father process, the one which started it, exits or dies), init will automatically become its father process.</p>
<p>The init process allows you to get a trace of what your processes are doing, where they do come from, and whether they&#8217;re in a decent or zombie state.</p>
<h2 id="the-legacy-system-v-init">The legacy System V init</h2>
<p>UNIX System V is probably the most known UNIX system. It was one of the most used operating systems in the 80s-90s for servers. Its init system is the base of most of our actual systems&#8217; ones.</p>
<p><a href="http://savannah.nongnu.org/projects/sysvinit">SysVInit</a> design splits the boot process into several steps (usually 6 or 7 for recent versions) called &#8220;runlevels&#8221;:</p>
<ul>
<li>the runlevel 0 corresponds to the system shutdown</li>
<li>the runlevel 1 corresponds to the &#8220;single user&#8221; mode, it&#8217;s the step when the system&#8217;s basic components are started</li>
<li>the runlevel 2 corresponds to the &#8220;multi user&#8221; mode, all things that do not require networking are started there</li>
<li>the runlevel 3 corresponds to the &#8220;multi user with network&#8221; mode, all things requiring networking are started there</li>
<li>the runlevel 4 is usually unused, you can use it for specific custom purpose</li>
<li>the runlevel 5 usually starts the graphical user interface, but a lot of distributions already does it in runlevel 3</li>
<li>the runlevel 6 is used to reboot the system</li>
</ul>
<p>Services that need to be started when you start the system must provide what is called an &#8220;init script&#8221; which will tell SysVInit how to start the said service. This is usually a bash script which takes as argument either start, stop or restart. If none is provided by upstream, you still can write your own one. You then assign these services to some runlevels, and they will be started in a random order when SysVInit will reach this runlevel. Usually they are started in alphabetical order so you can specify the order you want by prefixing the init scripts with a numerical value such as &#8220;03&#8221; or &#8220;99&#8221; so start in n early or late stage of this runlevel. Everything is done one after another, each task waits for the previous one to finish before starting.</p>
<p>In /etc/inittab, you specify which runlevel you want to reach by default at startup, so you can tell it to stop at runlevel 3 for example. You will be able later to run &#8220;init 5&#8221; to start everything for example. You also can run &#8220;init 6&#8221; which is equivalent to &#8220;reboot&#8221; or &#8220;init 0&#8221; which is equivalent to &#8220;shutdown now&#8221;</p>
<h2 id="the-new-generation-init-systems">The new generation init systems</h2>
<p>Here are four examples of alternatives to SysVInit. There are other but these are the most used.</p>
<h3 id="openrc">OpenRC</h3>
<p><a href="http://www.gentoo.org/proj/en/base/openrc/">OpenRC</a> is <a href="http://www.gentoo.org/">Gentoo</a>&#8216;s init process. It is not a standalone one as it relies on SysVInit, it&#8217;s only there to add handy features and performance to SysVInit.</p>
<p>OpenRC allows you to explicitly specify dependencies between services, which makes the task a lot easier than having to prepend numbers to services names. It also adds the ability to get configuration files separated from init scripts.</p>
<h3 id="runit">Runit</h3>
<p><a href="http://smarden.org/runit/">Runit</a> is a replacement to SysVInit that also handles runlevels. It is not compatible with the legacy ones, though. Runit splits the init process into three runlevels named &#8220;stages&#8221;:</p>
<ul>
<li>the stage 1 corresponds to the system initialization. If anything goes wrong here, runit drops you to a rescue shell.</li>
<li>the stage 2 corresponds to everything that needs to be started (like SysVInit&#8217;s runlevel 5)</li>
<li>the stage 3 corresponds to shutdown tasks.</li>
</ul>
<p>Runit can read and handle SysVInit runlevels through an external compatibility layer called runsvdir but this is not how it is intended to be run.</p>
<p>Runit&#8217;s goal is to be as small and light as possible, it does exactly what you ask it to, and nothing more. You end up with a system as small as possible, but you do not have to forget anything since it won&#8217;t automatically do it for you.</p>
<h3 id="upstart">Upstart</h3>
<p><a href="http://upstart.ubuntu.com/">Upstart</a> is an <a href="http://www.ubuntu.com/">Ubuntu</a> attempt to make the system boot faster. It is fully event-driven and hence only waits for stuff that needs to be waited for when it starts every process needed by the system. It allows to start all these processes in parallel making them wait for dependencies only once they need them. When a process fails or crashes, Upstart can handle this event to restart it automatically.</p>
<p>Upstart is fully compatible with SysVInit and the transition should be smooth and quite easy. Some software may need specific init scripts though, especially to take advantage of upstart features.</p>
<h3 id="systemd">systemd</h3>
<p><a href="http://www.freedesktop.org/wiki/Software/systemd">systemd</a> (yes, no caps here) is <a href="http://www.redhat.com/">Red Hat</a>&#8216;s attempt to make the boot smarter (and thus faster), especially for its desktop distribution: <a href="http://fedoraproject.org/">Fedora</a>. systemd is widely inspired from Upstart, the Upstart&#8217;s TODO list, and from Apple&#8217;s Mac OS X init system: launchd.</p>
<p>systemd is as lazy as possible. It does not handle &#8220;runlevels&#8221; but rather &#8220;targets&#8221;. Everything handled by systemd is called a &#8220;unit&#8221;. A unit can either be a &#8220;target&#8221; (runlevel equivalent) or a &#8220;service&#8221; (the software itself), a &#8220;socket&#8221;, a &#8220;mount&#8221; operation, an &#8220;automount&#8221; operation or even a &#8220;timer&#8221; (cron-like) which will run your service in a regular fashion.</p>
<p>Some targets are provided by default but you can create your owns as you wish, with the names you want. You can specify which target has to be reached by default at system startup. In each unit, you can specify before or after which unit it should be started, whether it requires or is required by other units, if it conflicts with other units, and to which target it belongs. This allows systemd to know which targets and services it should start before starting the specified default target. To each target corresponds a target.wants directory, where the unit which should be started with this target are symbolic-linked. The sockets and mount operations are kinda more specific. Mount and automount operations are auto-generated from /etc/fstab (auto-mounting means that the filesystem appears to be mounted, but it really is mounted only once it has been accessed, which leads to a consequent gain of time). If a socket unit corresponds to a service one, systemd supports the socket activation of this service, which means that the service will really be started only when another service starts to communicate with it.</p>
<p>systemd is a real source of conflict between people against it and people in favor of it. The main argument of people which are against it is that it does too many things, it&#8217;s too complex and ships too many functionalities. I think this is a fake problem, since most of the functionalities are optional (and thus can be disabled), and everything is split into several binaries (systemd doesn&#8217;t do all this stuff itself but calls tools that it ships to do so). It is fully modular, and not modular like its &#8220;opponents&#8221;.</p>
<p>One of the interesting tools provided by systemd is the &#8220;journal&#8221;. The journal is basically a logging utility directly integrated in the init process (well, it actually only communicates with it, it&#8217;s not <em>really</em> in it). This allows you to get rid of an external logging utility such as syslog-ng or rsyslog. You can browse all the logs with the &#8220;journalctl&#8221; command which allows you to apply a lot of filters on them.</p>
<p>A really interesting serie of blog posts by Lennart Poettering (systemd&#8217;s lead developer) is available <a href="http://www.freedesktop.org/wiki/Software/systemd">here</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Traits extended by one-line case classes</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2012/06/21/traits-extended-by-one-line-case-classes/</link>
		
		<dc:creator><![CDATA[Rodolphe Belouin]]></dc:creator>
		<pubDate>Thu, 21 Jun 2012 00:00:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Developers]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2012/06/21/traits-extended-by-one-line-case-classes/</guid>

					<description><![CDATA[Let&#39;s start talking about Scala, that pretty language making you able to use both object-oriented and functional programming paradigms.If you&#39;ve never heard about it, take a look at Scala School. You have to be at ease with trait and case class concepts to understand this post. We all agree: keeping an abstract layer in your [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Let&#39;s start talking about Scala, that pretty language making you able to use both object-oriented and functional programming paradigms.<br />If you&#39;ve never heard about it, take a look at <a href="http://twitter.github.com/scala_school/">Scala School</a>. You have to be at ease with trait and case class concepts to understand this post.</p>
<p><span id="more-2781"></span></p>
<p>We all agree: keeping an abstract layer in your code is something good, but it&#39;s often painful when you have to rewrite n-times some children having a similar implementation.<br />I always try to keep that children readable and fast understandable by making them one-liners. Adding a child becomes quite easy, even for a non-scala developer.</p>
<h2 id="trivial-trait">Trivial trait</h2>
<p>Let&#39;s define a trait that will be the minimal representation of a message.</p>
<pre><code class="language-scala">trait Message {
  def id: String
  def content: String
}

case class DefaultMessage(id: String, content: String) extends Message
case class FromToMessage(id: String, content: String, from: String, to: String) extends Message
</code></pre>
<p>No need for writing overriding methods. Actually, <em>id</em> and <em>content</em> parameters are defined as methods that implicitly override Message&#39;s methods. Nice, isn&#39;t it?</p>
<h2 id="trait-using-serialization">Trait using serialization</h2>
<p>OK, that was quite simple. But how will you do if you have to create custom serializer object for each message type? In that example, we will be using the lift framework to (de)serialize JSON.</p>
<pre><code class="language-scala">trait MessageSerializer[M &lt;: Message] {
  implicit val format = DefaultFormats

  def apply(m: M): String = {
    Serialization.write(m)
  }

  def unapply(s: String)(implicit mf: Manifest[M]): Option[M] = {
    for {
      jvalue &lt;- JsonParser.parseOpt(s)
      m &lt;- jvalue.extractOpt[M]
    } yield m
  }
}

object DefaultMessageSerializer extends MessageSerializer[DefaultMessage]
object FromToMessageSerializer extends MessageSerializer[FromToMessage]
</code></pre>
<p>If you don&#39;t know what are apply and unapply methods, just take a look at this sample code to understand their usage:</p>
<pre><code class="language-scala">/* implicit call to apply method */
val a = DefaultMessage(&quot;1234&quot;, &quot;Hello world!&quot;)
println(DefaultMessageSerializer(a)) // print: {&quot;id&quot;: &quot;1234&quot;, &quot;content&quot;: &quot;Hello world!&quot;}

/* implicit call to unapply method */
&quot;&quot;&quot;{&quot;id&quot;: &quot;5678&quot;, &quot;content&quot;: &quot;Love&quot;, &quot;from&quot;: &quot;me&quot;, &quot;to&quot;: &quot;you&quot;}&quot;&quot;&quot; match {
  case FromToMessageSerializer(m) =&gt; println(m) // print FromToMessage(&quot;5678&quot;, &quot;Love&quot;, &quot;me&quot;, &quot;you&quot;)
  case _ =&gt; println(&quot;error&quot;)
}
</code></pre>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
