<liclass="toctree-l3"><aclass="reference internal"href="#configuring-nginx-for-let-s-encrypt-and-https-redirection">8.4.5. Configuring nginx for Let's Encrypt and HTTPS redirection</a></li>
<liclass="toctree-l3"><aclass="reference internal"href="#configuring-nginx-https-server-with-uwsgi-upstream">8.4.7. Configuring nginx HTTPS server with uWSGI upstream</a></li>
<liclass="toctree-l3"><aclass="reference internal"href="#complete-sample-bottle-hosting-type-manifest-listing">8.4.8. Complete __sample_bottle_hosting type manifest listing</a></li>
</ul>
</li>
<liclass="toctree-l2"><aclass="reference internal"href="#creating-sample-bottle-hosting-type-gencode-remote">8.5. Creating __sample_bottle_hosting type gencode-remote</a></li>
<h1><spanclass="section-number">8. </span>Dive into real world cdist<aclass="headerlink"href="#dive-into-real-world-cdist"title="Permalink to this headline">¶</a></h1>
<sectionid="introduction">
<h2><spanclass="section-number">8.1. </span>Introduction<aclass="headerlink"href="#introduction"title="Permalink to this headline">¶</a></h2>
<p>This walkthrough shows real world cdist configuration example.</p>
<p>Sample target host is named <strong>test.ungleich.ch</strong>.
Just replace <strong>test.ungleich.ch</strong> with your target hostname.</p>
<p>Our goal is to configure python application hosting. For writing sample
application we will use <aclass="reference external"href="http://bottlepy.org">Bottle</a> WSGI micro web-framework.
It will use PostgreSQL database and it will list items from <strong>items</strong> table.
It will be served by uWSGI server. We will also use the Nginx web server
as a reverse proxy and we want HTTPS.
For HTTPS we will use Let's Encrypt certificate.</p>
<p>For setting up hosting we want to use cdist so we will write a new type
for that. This type will:</p>
<ulclass="simple">
<li><p>install required packages</p></li>
<li><p>create OS user, user home directory and application home directory</p></li>
<p>Our type will not create the actual python application. Its intention is only
to configure hosting for specified user and project. It is up to the user to
create his/her applications.</p>
<p>So let's start.</p>
</section>
<sectionid="creating-type-layout">
<h2><spanclass="section-number">8.2. </span>Creating type layout<aclass="headerlink"href="#creating-type-layout"title="Permalink to this headline">¶</a></h2>
<p>We will create a new custom type. Let's call it <strong>__sample_bottle_hosting</strong>.</p>
<p>Go to <strong>~/.cdist/type</strong> directory (create it if it does not exist) and create
<h2><spanclass="section-number">8.3. </span>Creating __sample_bottle_hosting type parameters<aclass="headerlink"href="#creating-sample-bottle-hosting-type-parameters"title="Permalink to this headline">¶</a></h2>
<p>Our type will be configurable through the means of parameters. Let's define
the following parameters:</p>
<dlclass="simple">
<dt>projectname</dt><dd><p>name for the project, needed for uWSGI ini file</p>
</dd>
<dt>user</dt><dd><p>user name</p>
</dd>
<dt>domain</dt><dd><p>target host domain, needed for Let's Encrypt certificate.</p>
</dd>
</dl>
<p>We define parameters to make our type reusable for different projects, user and domain.</p>
<h2><spanclass="section-number">8.4. </span>Creating __sample_bottle_hosting type manifest<aclass="headerlink"href="#creating-sample-bottle-hosting-type-manifest"title="Permalink to this headline">¶</a></h2>
<p>Next step is to define manifest (~/.cdist/type/__sample_bottle_hosting/manifest).
We also want our type to currently support only Devuan. So we will start by
checking target host OS. We will use <aclass="reference external"href="cdist-reference.html#explorers">os</a>
echo "OS $os currently not supported">&2
exit 1
;;
esac
</pre></div>
</div>
<p>If target host OS is not Devuan then we print error message to stderr
and exit. For other OS-es support we should check and change package names
we should install, because packages differ in different OS-es and in different
OS distributions like GNU/Linux distributions. There can also be a different
configuration locations (e.g. nginx config directory could be in /usr/local tree).
If we detected unsupported OS we should error out. cdist will stop configuration
process and output error message.</p>
<sectionid="creating-user-and-user-directories">
<h3><spanclass="section-number">8.4.1. </span>Creating user and user directories<aclass="headerlink"href="#creating-user-and-user-directories"title="Permalink to this headline">¶</a></h3>
<p>Then we create user and his/her home directory and application home directory.
We will use existing cdist types <aclass="reference external"href="man7/cdist-type__user.html">__user</a> and <aclass="reference external"href="man7/cdist-type__directory.html">__directory</a>:</p>
<p>First we define <em>user</em>, <em>home</em> and <em>apphome</em> variables. User is defined by type's
<strong>user</strong> parameter. Here we use <strong>require</strong> which is cdist's way to define dependencies.
User home directory should be created <strong>after</strong> user is created. And application
home directory is created <strong>after</strong> both user and user home directory are created.
For details on <strong>require</strong> see <aclass="reference external"href="cdist-manifest.html#dependencies">Dependencies</a>.</p>
</section>
<sectionid="installing-packages">
<h3><spanclass="section-number">8.4.2. </span>Installing packages<aclass="headerlink"href="#installing-packages"title="Permalink to this headline">¶</a></h3>
<p>Install required packages using existing <aclass="reference external"href="man7/cdist-type__package.html">__package</a> type.
Before installing package we want to update apt package index using
<h3><spanclass="section-number">8.4.3. </span>Creating PostgreSQL database<aclass="headerlink"href="#creating-postgresql-database"title="Permalink to this headline">¶</a></h3>
<p>Create PostgreSQL database using <aclass="reference external"href="man7/cdist-type__postgres_database.html">__postgres_database</a>
and <aclass="reference external"href="man7/cdist-type__postgres_role.html">__postgres_role</a> for creating database user:</p>
<divclass="highlight-default notranslate"><divclass="highlight"><pre><span></span>#PostgreSQL db & user
<h3><spanclass="section-number">8.4.4. </span>Configuring uWSGI<aclass="headerlink"href="#configuring-uwsgi"title="Permalink to this headline">¶</a></h3>
<p>Configure uWSGI using <aclass="reference external"href="man7/cdist-type__file.html">__file</a> type:</p>
<h3><spanclass="section-number">8.4.5. </span>Configuring nginx for Let's Encrypt and HTTPS redirection<aclass="headerlink"href="#configuring-nginx-for-let-s-encrypt-and-https-redirection"title="Permalink to this headline">¶</a></h3>
<p>Next configure nginx for Let's Encrypt and for HTTP -> HTTPS redirection. For this
purpose we will create new type <strong>__sample_nginx_http_letsencrypt_and_ssl_redirect</strong>
<h3><spanclass="section-number">8.4.6. </span>Configuring certificate creation<aclass="headerlink"href="#configuring-certificate-creation"title="Permalink to this headline">¶</a></h3>
<p>After HTTP nginx configuration we will create Let's Encrypt certificate using
<h3><spanclass="section-number">8.4.7. </span>Configuring nginx HTTPS server with uWSGI upstream<aclass="headerlink"href="#configuring-nginx-https-server-with-uwsgi-upstream"title="Permalink to this headline">¶</a></h3>
<p>Then we can configure nginx HTTPS server that will use created Let's Encrypt certificate:</p>
<h3><spanclass="section-number">8.4.8. </span>Complete __sample_bottle_hosting type manifest listing<aclass="headerlink"href="#complete-sample-bottle-hosting-type-manifest-listing"title="Permalink to this headline">¶</a></h3>
<p>Here is complete __sample_bottle_hosting type manifest listing,
located in ~/.cdist/type/__sample_bottle_hosting/manifest:</p>
<h2><spanclass="section-number">8.5. </span>Creating __sample_bottle_hosting type gencode-remote<aclass="headerlink"href="#creating-sample-bottle-hosting-type-gencode-remote"title="Permalink to this headline">¶</a></h2>
<h2><spanclass="section-number">8.6. </span>Creating __sample_nginx_http_letsencrypt_and_ssl_redirect type<aclass="headerlink"href="#creating-sample-nginx-http-letsencrypt-and-ssl-redirect-type"title="Permalink to this headline">¶</a></h2>
<p>Let's now create <strong>__sample_nginx_http_letsencrypt_and_ssl_redirect</strong> type:</p>
<h2><spanclass="section-number">8.7. </span>Creating init manifest<aclass="headerlink"href="#creating-init-manifest"title="Permalink to this headline">¶</a></h2>
<p>After cdist configuration is successfully finished our host is ready.</p>
</section>
<sectionid="creating-python-bottle-application">
<h2><spanclass="section-number">8.9. </span>Creating python bottle application<aclass="headerlink"href="#creating-python-bottle-application"title="Permalink to this headline">¶</a></h2>
<p>We now need to create Bottle application. As you remember from the beginning
of this walkthrough our type does not create the actual python application,
its intention is only to configure hosting for specified user and project.
It is up to the user to create his/her applications.</p>
<h3><spanclass="section-number">8.9.1. </span>Preparing database<aclass="headerlink"href="#preparing-database"title="Permalink to this headline">¶</a></h3>
<p>We need to prepare database for our application. Create table and
<spanclass="n">psql</span><spanclass="o">-</span><spanclass="n">c</span><spanclass="s2">"insert into items(item) values('spam');"</span>
<spanclass="n">psql</span><spanclass="o">-</span><spanclass="n">c</span><spanclass="s2">"insert into items(item) values('eggs');"</span>
<spanclass="n">psql</span><spanclass="o">-</span><spanclass="n">c</span><spanclass="s2">"insert into items(item) values('sausage');"</span>
</pre></div>
</div>
</section>
<sectionid="creating-application">
<h3><spanclass="section-number">8.9.2. </span>Creating application<aclass="headerlink"href="#creating-application"title="Permalink to this headline">¶</a></h3>
<spanclass="n">db</span><spanclass="o">.</span><spanclass="n">execute</span><spanclass="p">(</span><spanclass="s1">'select * from items'</span><spanclass="p">)</span>
<p>We have configured uWSGI with <strong>touch-reload = $projectname/wsgi.py</strong> so after
we have changed our <strong>wsgi.py</strong> file uWSGI reloads the application.</p>
<p>Our application selects and lists items from <strong>items</strong> table.</p>
</section>
<sectionid="opening-application">
<h3><spanclass="section-number">8.9.3. </span>Opening application<aclass="headerlink"href="#opening-application"title="Permalink to this headline">¶</a></h3>
Built with <ahref="http://sphinx-doc.org/">Sphinx</a> using a <ahref="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <ahref="https://readthedocs.org">Read the Docs</a>.