<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://en.wiki.guifi.net/w/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://en.wiki.guifi.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Conxuro</id>
		<title>Guifi.net - English Wiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://en.wiki.guifi.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Conxuro"/>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Special:Contributions/Conxuro"/>
		<updated>2026-07-29T01:31:40Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.22.0</generator>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_plug-ins</id>
		<title>Cloudy plug-ins</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_plug-ins"/>
				<updated>2015-12-03T17:23:23Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is a plug-in? ==&lt;br /&gt;
&lt;br /&gt;
Cloudy is a Debian-based Linux distribution that provides users a simple and convenient web interface to manage different services that are to be used in a Community Network (in our case, Guifi).&lt;br /&gt;
&lt;br /&gt;
At the same time, Cloudy offers a set of tools that allow a user to add a service to the system without need for advanced knowledges on networking or computers in general. These services are automatically published to the Community Network, so that anybody using Cloudy can use this new service.&lt;br /&gt;
&lt;br /&gt;
'''Plug-ins''' are the modular pieces of code that allow adding and removing these services. Therefore, we understand thata plug-in is a program or a piece of software that a user can add to the Cloudy distribution and that can be managed in a simple way from the web interface provided by Cloudy.&lt;br /&gt;
&lt;br /&gt;
== Adding services to Cloudy ==&lt;br /&gt;
&lt;br /&gt;
=== A brief introduction ===&lt;br /&gt;
&lt;br /&gt;
This guide will walk you through the process of adding a new service to Cloudy.&lt;br /&gt;
&lt;br /&gt;
In order to be clear and provide examples, we are going to be integrating a very simple service showing snippets of code along the way.&lt;br /&gt;
To follow the tutorial or to add complex services, will be nice any knowledge of Bash&amp;lt;ref name=&amp;quot;Bash&amp;quot;&amp;gt;(http://www.tldp.org/LDP/Bash-Beginners-Guide/Bash-Beginners-Guide.pdf)&amp;lt;/ref&amp;gt; and PHP&amp;lt;ref name=&amp;quot;PHP&amp;quot;&amp;gt;(https://php.net/manual/es/index.php)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the sake of simplicity, we will use Pastecat&amp;lt;ref name=&amp;quot;Pastecat&amp;quot;&amp;gt;(https://github.com/mvdan/pastecat)&amp;lt;/ref&amp;gt;. It is a good candidate because:&lt;br /&gt;
&lt;br /&gt;
* It's a standalone program&lt;br /&gt;
* It only needs to be installed in one node (no federation/syncrhonization)&lt;br /&gt;
* It's Built with Go, it's easy to distribute and deploy&lt;br /&gt;
* It doesn't need a configuration file nor any kind of setup&lt;br /&gt;
* It's very lightweight on resources&lt;br /&gt;
&lt;br /&gt;
=== Getting the binary ===&lt;br /&gt;
&lt;br /&gt;
The first thing we have to figure out is how to download and install the binary on Cloudy. Most software out there is already available as a package on Debian, but Pastecat isn't. If it were, it would be a matter of just running the command &amp;lt;code&amp;gt;apt-get install pastecat&amp;lt;/code&amp;gt; from PHP. Therefore we'll have to get it from someplace else.&lt;br /&gt;
&lt;br /&gt;
One option is to fetch the source and build it ourselves. This often means, however, that Cloudy should include a lot of build tools and libraries. In the case of Go, that would mean having its toolchain installed, which isn't very practical.&lt;br /&gt;
&lt;br /&gt;
A better option when the Debian package isn't available is to download the binary from upstream trusted sources via HTTPS and, preferably, checking digests or using signatures. We can use Github's releases page for that. Both options leave us with an executable file that we should be able to run directly on Cloudy.&lt;br /&gt;
&lt;br /&gt;
In this particular case we are going to download the binaries from the git repository with the following command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;wget https://github.com/mvdan/pastecat/releases/download/v0.3.0/pastecat_linux_386_v0.3.0&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that in this case we are downloading a specific version for a Linux with a 386 architecture.&lt;br /&gt;
&lt;br /&gt;
Note that having the service as a Debian package has many advantages:&lt;br /&gt;
&lt;br /&gt;
* Updates are simple and need no extra work from Cloudy&lt;br /&gt;
* The package is compiled and built by Debian in a trusted way&lt;br /&gt;
* An init.d file is already provided&lt;br /&gt;
* Debian packages often contain small patches and fixes&lt;br /&gt;
&lt;br /&gt;
=== Testing it out ===&lt;br /&gt;
&lt;br /&gt;
Before adding Pastecat as a Cloudy service, we can configure and start it ourselves directly (i.e. manually), to see if it works and how. This way we can better understand what configuration options or command line parameters are we will need to run it as a service, and also to manage it once it is running.&lt;br /&gt;
&lt;br /&gt;
=== Adding the controller ===&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;web/plug/controllers&amp;lt;/code&amp;gt; we have one PHP file per service, which we call &amp;amp;quot;the controller&amp;amp;quot;. This is the code that will run when we enter the services page on the Cloudy web interface.&lt;br /&gt;
&lt;br /&gt;
==== Adding the index function ====&lt;br /&gt;
&lt;br /&gt;
We also want our service to be integrated in the Cloudy web structure. To do this, a few PHP scripts need to be created and added to our device. Altogether, and by the time being, we'll need to create a total of 2 scripts: &amp;lt;code&amp;gt;pastecat.PHP&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;pastecat.menu.PHP&amp;lt;/code&amp;gt;. The first one is the controller itself, this is, the script that renders the page and has all the information such as buttons or redirections. The other one is what allows our service to show up in the upper menu bar of Cloudy's web interface.&lt;br /&gt;
&lt;br /&gt;
The menu code will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;?PHP&lt;br /&gt;
//peerstreamer.menu.PHP&lt;br /&gt;
addMenu('Pastecat','pastecat','Clommunity');&amp;lt;/pre&amp;gt;&lt;br /&gt;
By now, we'll use a very simple PHP script in the controller:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;?PHP&lt;br /&gt;
//pastecat&lt;br /&gt;
$title=&amp;amp;quot;Pastecat&amp;amp;quot;;&lt;br /&gt;
&lt;br /&gt;
function index(){&lt;br /&gt;
    global $paspath,$title;&lt;br /&gt;
    global $staticFile;&lt;br /&gt;
&lt;br /&gt;
    $page=hlc(t($title));&lt;br /&gt;
    $page .= hl(t(&amp;amp;quot;Minimalist pastebin engine written in Go&amp;amp;quot;),4);&lt;br /&gt;
    $page .= par(t(&amp;amp;quot;A simple and self-hosted pastebin service written in Go&amp;amp;quot;).' '.t(&amp;amp;quot;Can use a variety of storage backends&amp;amp;quot;).' '.t(&amp;amp;quot; Designed to optionally remove pastes after a certain period of time.&amp;amp;quot;).' '.(&amp;amp;quot;If using a persistent storage backend, pastes will be kept between runs.&amp;amp;quot;).' '.t(&amp;amp;quot;This software runs the&amp;amp;quot;).' '.&amp;amp;quot;&amp;amp;lt;a href='http://paste.cat'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;paste.cat&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/a&amp;amp;gt;&amp;amp;quot;. t(&amp;amp;quot; public service.&amp;amp;quot;));&lt;br /&gt;
&lt;br /&gt;
    return(array('type' =&amp;amp;gt; 'render','page' =&amp;amp;gt; $page));&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
In our Cloudy system, these files must be placed at &amp;lt;code&amp;gt;/var/local/cDistro/plug/&amp;lt;/code&amp;gt; the first one at &amp;lt;code&amp;gt;menus&amp;lt;/code&amp;gt; directory and the second at &amp;lt;code&amp;gt;controllers&amp;lt;/code&amp;gt; directory. Once we've done this, we can go to our Cloudy system and access our new Pastecat.&lt;br /&gt;
&lt;br /&gt;
==== Making the controller install the service ====&lt;br /&gt;
&lt;br /&gt;
As said before, this step is made much more easier if the service is packaged in Debian. Since Pastecat isn't, we'll have to do it manually. This usually involves a combination of &amp;lt;code&amp;gt;wget&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;chmod&amp;lt;/code&amp;gt;. It is generally a good idea to keep the service's files under &amp;lt;code&amp;gt;/opt/SERVICENAME&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In our particular case, the first thing we need to do is downloading the binary from the release. In order to do this we will make use of the mentioned &amp;lt;code&amp;gt;wget&amp;lt;/code&amp;gt; command. Given a URL to a file, this command allows us to download this file in our system, and this is what we will do in our system (as mentioned before):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;wget https://github.com/mvdan/pastecat/releases/download/v0.3.0/pastecat_linux_386_v0.3.0&amp;lt;/pre&amp;gt;&lt;br /&gt;
Once we have the binary, we just need to move it to a directory where executable files use to be located. In our case, we will use the directory /opt/pastecat/. To move these files through our system we will use the command &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt;. However, first of all we need to create the directory where we will place our binary. To do this we use the &amp;lt;code&amp;gt;mkdir&amp;lt;/code&amp;gt; command as is shown below:&lt;br /&gt;
&lt;br /&gt;
mkdir -p /opt/pastecat/&lt;br /&gt;
&lt;br /&gt;
Once we have our directory created, it is time to move the binary there:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;mv current_directory/pastecat_linux_386 /opt/pastecat/&amp;lt;/pre&amp;gt;&lt;br /&gt;
where current_directory is the directory where we previously downloaded the binary. Since the binary name depends on the architecture, in order to simplfy the controller's code, we will change its name to something more simple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;mv /opt/pastecat/pastecat_linux_386 /opt/pastecat/pastecat&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now our binary is called &amp;lt;code&amp;gt;pastecat&amp;lt;/code&amp;gt; insted of &amp;lt;code&amp;gt;pastecat_linux_386&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These steps are the minimum requiered to install a service which is not provided in the Debian official repositories. However, to an end user, it would look like a nightmare to run these commands in a console connected through ssh to its device, so what we are going to do now, is create a bash script which will be called later from the web interface by clicking a button.&lt;br /&gt;
&lt;br /&gt;
This script is the first version of the pastecat controller. For the time being, We will just include a function to install pastecat in a device. Later we will include some other functions to add more facilities to our service.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/bash&lt;br /&gt;
PCPATH=&amp;amp;quot;/opt/pastecat/&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
doInstall() {&lt;br /&gt;
    if isInstall&lt;br /&gt;
    then&lt;br /&gt;
        echo &amp;amp;quot;Pastecat is already installed.&amp;amp;quot;&lt;br /&gt;
        return&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    # Creating directory and switching&lt;br /&gt;
    mkdir -p $pcpath &amp;amp;amp;&amp;amp;amp; cd $pcpath&lt;br /&gt;
&lt;br /&gt;
    # Getting file&lt;br /&gt;
    wget https://github.com/mvdan/pastecat/releases/download/v0.3.0/pastecat_linux_386_v0.3.0&lt;br /&gt;
&lt;br /&gt;
    # Changing name so controller can invoke it generically&lt;br /&gt;
    mv pastecat_linux_386 pastecat&lt;br /&gt;
    chmod +x pastecat&lt;br /&gt;
    &lt;br /&gt;
    cd -&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
isInstalled() {&lt;br /&gt;
    [ -d $pcpath ] &amp;amp;amp;&amp;amp;amp; return 0&lt;br /&gt;
    return 1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
case $1 in&lt;br /&gt;
    &amp;amp;quot;install&amp;amp;quot;)&lt;br /&gt;
        shift&lt;br /&gt;
        doInstall $@&lt;br /&gt;
        ;;&lt;br /&gt;
esac&amp;lt;/pre&amp;gt;&lt;br /&gt;
We can see how the lasts steps are done within the same function, allowing us to install the software in the device.&lt;br /&gt;
&lt;br /&gt;
==== Making the controller use Pastecat ====&lt;br /&gt;
&lt;br /&gt;
===== Start the service =====&lt;br /&gt;
&lt;br /&gt;
The next thing we want is our software to be used through the web interface. In order to do this, we will include a new option to the main page of pastecat, and also integrate a new function to the controller script to manage the binary. We will add the button like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$page .= addButton(array('label'=&amp;amp;gt;t('Create a Pastecat server'),'href'=&amp;amp;gt;$staticFile.'/pastecat/publish'));&amp;lt;/pre&amp;gt;&lt;br /&gt;
after the &amp;lt;code&amp;gt;Pastecat is installed&amp;lt;/code&amp;gt; message. The next thing will be implementing the function &amp;lt;code&amp;gt;publish&amp;lt;/code&amp;gt; in the same PHP. This function is the responsible of calling the appropiate function in the controller and to announce our server usign the avahi technology. The difference with this function is that it requieres a form to introduce data, so in the end we will have a total of 2 functions: a get and a post:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function publish_get() {&lt;br /&gt;
    global $pcpath,$title;&lt;br /&gt;
    global $staticFile;&lt;br /&gt;
&lt;br /&gt;
    $page = hlc(t($title));&lt;br /&gt;
    $page .= hlc(t('Publish a pastecat server'),2);&lt;br /&gt;
    $page .= par(t(&amp;amp;quot;Write the port to publish your Pastecat service&amp;amp;quot;));&lt;br /&gt;
    $page .= createForm(array('class'=&amp;amp;gt;'form-horizontal'));&lt;br /&gt;
    $page .= addInput('description',t('Describe this server'));&lt;br /&gt;
    $page .= addSubmit(array('label'=&amp;amp;gt;t('Publish'),'class'=&amp;amp;gt;'btn btn-primary'));&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Cancel'),'href'=&amp;amp;gt;$staticFile.'/peerstreamer'));&lt;br /&gt;
&lt;br /&gt;
    return(array('type' =&amp;amp;gt; 'render','page' =&amp;amp;gt; $page));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function publish_post() {&lt;br /&gt;
    $port = $_POST['port'];&lt;br /&gt;
    $description = $_POST['description'];&lt;br /&gt;
    $ip = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;lt;pre&amp;amp;gt;&amp;amp;quot;;&lt;br /&gt;
    $page .= _pcsource($description);&lt;br /&gt;
    $page .= &amp;amp;quot;&amp;amp;lt;/pre&amp;amp;gt;&amp;amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    return(array('type' =&amp;amp;gt; 'render','page' =&amp;amp;gt; $page));&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
As we can see, in the &amp;lt;code&amp;gt;post&amp;lt;/code&amp;gt; function we are invoking another function. The reason to do this is to write a more simple and modular code. In this function, we are finally calling the script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function _pcsource($port,$description) {&lt;br /&gt;
    global $pcpath,$pcprogram,$title,$pcutils,$avahi_type,$port;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
    $device = getCommunityDev()['output'][0];&lt;br /&gt;
    $ipserver = getCommunityIP()['output'][0];&lt;br /&gt;
&lt;br /&gt;
    if ($description == &amp;amp;quot;&amp;amp;quot;) $description = $type;&lt;br /&gt;
&lt;br /&gt;
    $cmd = $pcutils.&amp;amp;quot; publish '$port' '$description';&lt;br /&gt;
    execute_program_detached($cmd);&lt;br /&gt;
&lt;br /&gt;
    $page .= t($ipserver);&lt;br /&gt;
    $page .= par(t('Published this server.'));&lt;br /&gt;
&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Back'),'href'=&amp;amp;gt;$staticFile.'/pastecat'));&lt;br /&gt;
&lt;br /&gt;
    return($page)&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
The next thing to do will be create the function &amp;lt;code&amp;gt;publish&amp;lt;/code&amp;gt; in the controller, so we will add a new function to the basic controller we had back at section '''3.2'''. We will add a new flag called publish, so the first executed part of the script will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if [ $# -lt 1 ]&lt;br /&gt;
then&lt;br /&gt;
    doHelp&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
case $1 in&lt;br /&gt;
    &amp;amp;quot;install&amp;amp;quot;)&lt;br /&gt;
        shift&lt;br /&gt;
        doInstall $@&lt;br /&gt;
        ;;&lt;br /&gt;
    &amp;amp;quot;publish&amp;amp;quot;)&lt;br /&gt;
        shift&lt;br /&gt;
        doServer $@&lt;br /&gt;
        ;;&lt;br /&gt;
esac&amp;lt;/pre&amp;gt;&lt;br /&gt;
As we can see, when the script's first argument is &amp;lt;code&amp;gt;publish&amp;lt;/code&amp;gt;, we shift the rest of arguments and call the function &amp;lt;code&amp;gt;doServer&amp;lt;/code&amp;gt;. In this function, we must start the service with the requiered arguments, so the first thing we'll do is put the arguments into local variables. Once we do that the common thing would be to launche the Pastecat server, but since it might be called with root permissions (and this is bad) we must run it as a &amp;lt;code&amp;gt;nobody&amp;lt;/code&amp;gt; user. The issue is that the &amp;lt;code&amp;gt;nobody&amp;lt;/code&amp;gt; user has merely no permissions... and pastecat need some permissions to create folders and text files. In order to allow the &amp;lt;code&amp;gt;nobody&amp;lt;/code&amp;gt; user to do that, first of all we will create a folder and grant permissions to almost everyone to it. We will use &amp;lt;code&amp;gt;chmod&amp;lt;/code&amp;gt; again. Now, the user can create files and directories within this directory, so we can now run pastecat. Finally, we keep the pid in a variable in case we want to use it in later updates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;doServer() {&lt;br /&gt;
    # Turning machine into a server&lt;br /&gt;
&lt;br /&gt;
    local port=${1:-&amp;amp;quot;&amp;amp;quot;}&lt;br /&gt;
    local description=${2:-&amp;amp;quot;&amp;amp;quot;}&lt;br /&gt;
    local ip=${3:-&amp;amp;quot;0.0.0.0&amp;amp;quot;}&lt;br /&gt;
&lt;br /&gt;
    # Creating directory with nobody permissions&lt;br /&gt;
    mkdir -p &amp;amp;quot;/var/local/pastecat&amp;amp;quot;&lt;br /&gt;
    chmod 777 &amp;amp;quot;/var/local/pastecat&amp;amp;quot; &amp;amp;amp;&amp;amp;amp; cd &amp;amp;quot;/var/local/pastecat&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # Running pastecat &lt;br /&gt;
    cmd='su '$PCUSER' -c &amp;amp;quot;{ '$PCPATH$PCPROG' -l :'$port' &amp;amp;gt; '$LOGFILE' 2&amp;amp;gt;&amp;amp;amp;1 &amp;amp;amp; }; echo \$!&amp;amp;quot;'&lt;br /&gt;
    pidpc=$(eval $cmd)          # keeping PID for future needs...&lt;br /&gt;
&lt;br /&gt;
    cd -&lt;br /&gt;
&lt;br /&gt;
    # Using the PID, we could carry on process control so if the pastecat process die, we can also&lt;br /&gt;
    # stop the avahi process to avoid &amp;amp;quot;false connections&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that we are using some global variables that were not defined before such as &amp;lt;code&amp;gt;PCUSER&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LOGFILE&amp;lt;/code&amp;gt;. By default, we set these variables like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;PCPATH=&amp;amp;quot;/opt/pastecat/&amp;amp;quot;&lt;br /&gt;
PCPROG=&amp;amp;quot;pastecat&amp;amp;quot;&lt;br /&gt;
LOGFILE=&amp;amp;quot;/dev/null&amp;amp;quot;&lt;br /&gt;
PCUSER=&amp;amp;quot;nobody&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Stop the service =====&lt;br /&gt;
&lt;br /&gt;
Sometimes, we may also want to stop out service, so we will provide a button to do so. The first thing would be creating the button, but if we think a little, we will figure out that before doing this, we need a way to know if our service is running. In addition, we also need a way to stop our service. Since we are running on Linux, we can easily achieve that by using the &amp;lt;code&amp;gt;kill&amp;lt;/code&amp;gt; command. The thing is that to use this command, we need the Process ID (PID). Luckily for us, we already kept this number when we created the pastecat server with &amp;lt;code&amp;gt;pidpc=$(eval $cmd)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now that we have everything we need to kill our process, let's provide a way so the PHP can detect whether Pastecat is running or not. An easy and resulting way to do this is storing some useful data in a file and delete this file when pastecat is stopped. This way, we make sure that this file will only exists when Pastecat is running. This file will be created from the controller adding the following lines right below the sentence we mentioned in the previous paragraph:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Writting server info to file&lt;br /&gt;
info=&amp;amp;quot;$pidpc http://$ip:$port&amp;amp;quot;          # Separator is space character&lt;br /&gt;
echo $info &amp;amp;gt; $PCFILE&amp;lt;/pre&amp;gt;&lt;br /&gt;
where &amp;lt;code&amp;gt;$PCFILE&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;/var/run/pc.info&amp;lt;/code&amp;gt;. Note that the content of this file will be the PID and the complete direction of our Pastecat server.&lt;br /&gt;
&lt;br /&gt;
Now we have a way to know if our server is up or down, so we can add the &amp;amp;quot;stop&amp;amp;quot; button in the web interfae. We will modify a little bit the PHP script that we had before, just by addind anther advertisement indicating whether Pastecat is up or down, and 2 more buttons if it is running. So, in our index function, within the condition that checks if Pastecat is installed we will have the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$page .= &amp;amp;quot;&amp;amp;lt;div class='alert alert-success text-center'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;Pastecat is installed&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/div&amp;amp;gt;\n&amp;amp;quot;;&lt;br /&gt;
if ( isRunning() ) {&lt;br /&gt;
    $page .= &amp;amp;quot;&amp;amp;lt;div class='alert alert-success text-center'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;Pastecat is running&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/div&amp;amp;gt;\n&amp;amp;quot;;&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Go to server'),'href'=&amp;amp;gt;'http://'. getCommunityIP()['output'][0] .':'. $port));&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Stop server'),'href'=&amp;amp;gt;$staticFile.'/pastecat/stop'));&lt;br /&gt;
} else  {&lt;br /&gt;
    $page .= &amp;amp;quot;&amp;amp;lt;div class='alert alert-error text-center'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;Pastecat is not running&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/div&amp;amp;gt;\n&amp;amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
$page .= addButton(array('label'=&amp;amp;gt;t('Create a Pastecat server'),'href'=&amp;amp;gt;$staticFile.'/pastecat/publish'));&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this piece of code, we can appreciate 2 new features in our code. The first one is a check function called &amp;lt;code&amp;gt;isRunning()&amp;lt;/code&amp;gt;. This function looks very similar to the function we used to check if Pastecat is installed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function isRunning() {&lt;br /&gt;
    // Returns whether pastecat is running or not&lt;br /&gt;
    global $pcfile;&lt;br /&gt;
&lt;br /&gt;
    return(file_exists($pcfile));   &lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
It is a simple as it seems, it just checks if the file we created when starting the server still exists. The second thing we can notice in the new PHP code is the existance of a new function called &amp;lt;code&amp;gt;stop&amp;lt;/code&amp;gt;. This function will invoke another function in the controller which will stop the pastecat:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function stop() {&lt;br /&gt;
    // Stops Pastecat server&lt;br /&gt;
    global $pcpath,$pcprogram,$title,$pcutils,$avahi_type,$port;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
    $cmd = $pcutils.&amp;amp;quot; stop &amp;amp;quot;;&lt;br /&gt;
    execute_program_detached($cmd);&lt;br /&gt;
&lt;br /&gt;
    return(array('type'=&amp;amp;gt;'redirect','url'=&amp;amp;gt;$staticFile.'/pastecat'));&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to make the controller understand this order, we will modify the case and add the new function. In the &amp;lt;code&amp;gt;case&amp;lt;/code&amp;gt; statement, we will add the following under the &amp;lt;code&amp;gt;install&amp;lt;/code&amp;gt; option:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;quot;stop&amp;amp;quot;)&lt;br /&gt;
    shift&lt;br /&gt;
    doStop $@&lt;br /&gt;
    ;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
This calls the function &amp;lt;code&amp;gt;doStop&amp;lt;/code&amp;gt; within the controller. This function will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;doStop() {&lt;br /&gt;
    # Stopping pastecat server&lt;br /&gt;
    pcpid=$(cat $PCFILE | cut -d' ' -f1)&lt;br /&gt;
    kill $pcpid&lt;br /&gt;
&lt;br /&gt;
    # Removing info file&lt;br /&gt;
    rm $PCFILE&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
This function just gets the pastecat's PID from the file we created before, kills the process and finally removes the file so the PHP scripts can know that pastecat is now down.&lt;br /&gt;
&lt;br /&gt;
Now we can create a pastecat instance server and stop it. However, there is still something missing: make the other users see our service. And this is why we are using avahi.&lt;br /&gt;
&lt;br /&gt;
=== Avahi service publishing ===&lt;br /&gt;
&lt;br /&gt;
On of the best things in Cloudy is the facility of publishing our service as a publication in the avahi network, allowing other users to know what we are offering and joining our service. To do this, we first need to add a few lines to the PHP controller, just after we've called the controller to start the pastecat instance. We will add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$description = str_replace(' ', '', $description);&lt;br /&gt;
$temp = avahi_publish($avahi_type, $description, $port, &amp;amp;quot;&amp;amp;quot;);&lt;br /&gt;
$page .= ptxt($temp);&amp;lt;/pre&amp;gt;&lt;br /&gt;
So in the end our function will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function _pcsource($port,$description) {&lt;br /&gt;
    global $pcpath,$pcprogram,$title,$pcutils,$avahi_type;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
    $device = getCommunityDev()['output'][0];&lt;br /&gt;
    $ipserver = getCommunityIP()['output'][0];&lt;br /&gt;
&lt;br /&gt;
    if ($description == &amp;amp;quot;&amp;amp;quot;) $description = $type;&lt;br /&gt;
&lt;br /&gt;
    $cmd = $pcutils.&amp;amp;quot; publish '$port' '$description'&amp;amp;quot;;&lt;br /&gt;
    execute_program_detached($cmd);&lt;br /&gt;
&lt;br /&gt;
    $page .= t($ipserver);&lt;br /&gt;
    $page .= par(t('Published this server.'));&lt;br /&gt;
    $description = str_replace(' ', '', $description);&lt;br /&gt;
    $temp = avahi_publish($avahi_type, $description, $port, &amp;amp;quot;&amp;amp;quot;);&lt;br /&gt;
    $page .= ptxt($temp);&lt;br /&gt;
&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Back'),'href'=&amp;amp;gt;$staticFile.'/pastecat'));&lt;br /&gt;
&lt;br /&gt;
    return($page)&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
With this simple step, we announced our service in the avahi network. However the work does not end here, there is still one more thing to do: create a button and program it so when clicked, it directly goes to our pastecat server.&lt;br /&gt;
&lt;br /&gt;
To do this there is a folder called &amp;lt;code&amp;gt;avahi&amp;lt;/code&amp;gt; within the &amp;lt;code&amp;gt;plug&amp;lt;/code&amp;gt; directory. The scripts that define the function carried on when the button is clicked are defined in different files within this directory, therefor we will create a new file called &amp;lt;code&amp;gt;pastecat.avahi.PHP&amp;lt;/code&amp;gt; which will contain this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;?PHP&lt;br /&gt;
// plug/avahi/pastecat.avahi.PHP&lt;br /&gt;
&lt;br /&gt;
addAvahi('pastecat','fpcserver');&lt;br /&gt;
&lt;br /&gt;
function fpcserver($dates){&lt;br /&gt;
    global $staticFile;&lt;br /&gt;
&lt;br /&gt;
    return (&amp;amp;quot;&amp;amp;lt;a class='btn' href='http://&amp;amp;quot; .$dates['ip'] .&amp;amp;quot;:&amp;amp;quot;. $dates['port'].&amp;amp;quot;'&amp;amp;gt;Go to server&amp;amp;lt;/a&amp;amp;gt;  &amp;amp;quot;);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will create a button besides the avahi announcement line that will point to our server.&lt;br /&gt;
&lt;br /&gt;
Now that we have our service announced, we want it to dissappear when we stop the pastecat service. This last step is very simple yet important. It consist of a few lines in the PHP function called stop. Until now, this function just called the controller and stopped the pastecat, but now it will also stop the avahi publication and show a flash comment so the user knwo it worked:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$temp = avahi_unpublish($avahi_type, $port);&lt;br /&gt;
$flash = ptxt($temp);&lt;br /&gt;
setFlash($flash);&amp;lt;/pre&amp;gt;&lt;br /&gt;
These lines will be added just after the &amp;lt;code&amp;gt;execute_program_detached($cmd)&amp;lt;/code&amp;gt; sentence in the stop function.&lt;br /&gt;
&lt;br /&gt;
=== Final ===&lt;br /&gt;
&lt;br /&gt;
Finally just comment that all the files implemented in this tutorial can be found in a Github repository, linked in the External Link section, also with this tutorial in Markdown format (md).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
&lt;br /&gt;
https://github.com/Clommunity/Doc/tree/master/plugins/pastecat&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;br /&gt;
[[ca:Cloudy_plug-ins]]&lt;br /&gt;
[[es:Cloudy_plug-ins]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_web_UI</id>
		<title>Cloudy web UI</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_web_UI"/>
				<updated>2015-12-03T17:14:32Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The Cloudy web User Interface (UI) uses an application called cDistro &amp;lt;ref name=&amp;quot;cdistro&amp;quot;&amp;gt;cDistro git repository: https://github.com/Clommunity/cDistro&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
''(Add what it is)''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
The cDistro configuration is placed in &amp;lt;s&amp;gt;/etc/cdistro.conf&amp;lt;/s&amp;gt; /etc/cloudy/cloudy.conf&lt;br /&gt;
&lt;br /&gt;
By default it has the following format:&lt;br /&gt;
&lt;br /&gt;
 #cdistro config&lt;br /&gt;
 SERVER=&amp;quot;/usr/bin/php&amp;quot;&lt;br /&gt;
 OPTS=&amp;quot;&amp;quot;&lt;br /&gt;
 BINDIP=&amp;quot;0.0.0.0&amp;quot;&lt;br /&gt;
 PORT=&amp;quot;7000&amp;quot;&lt;br /&gt;
 DOCROOT=&amp;quot;/var/local/cDistro&amp;quot;&lt;br /&gt;
 # SSHAUTH=1 &amp;lt;- check user with ssh2 connection http://www.php.net/manual/en/function.ssh2-auth-password.php (Require: libssh2-php)&lt;br /&gt;
 SSHAUTH=1&lt;br /&gt;
 # LOGIN=&amp;quot;root&amp;quot;&lt;br /&gt;
 ## PASSWORD = md5(md5('secret')) =&amp;gt; php -r 'echo md5(md5(&amp;quot;secret&amp;quot;)).&amp;quot;\n&amp;quot;;'&lt;br /&gt;
 #PASSWORD=&amp;quot;7022cd14c42ff272619d6beacdc9ffde&amp;quot;&lt;br /&gt;
 PORT_SSL=7443&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SERVER ===&lt;br /&gt;
&lt;br /&gt;
The path of the PHP executable.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/usr/bin/php&amp;quot; - in the case of Cloudy (Debian).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== OPTS ===&lt;br /&gt;
&lt;br /&gt;
PHP options.&lt;br /&gt;
&lt;br /&gt;
''(Add references or more info and an example)''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== BINDIP ===&lt;br /&gt;
&lt;br /&gt;
The IP address where the service will be listening.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;127.0.0.1&amp;quot; - will accept only petitions from localhost.&lt;br /&gt;
* &amp;quot;0.0.0.0&amp;quot; - will accept petitions from any address.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PORT ===&lt;br /&gt;
&lt;br /&gt;
The port opened by the service to listen to requests.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;7000&amp;quot; - opens the port 7000.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== DOCROOT ===&lt;br /&gt;
&lt;br /&gt;
The path of the cDistro application.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/var/local/cDistro&amp;quot; - in the case of Cloudy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SSLAUTH ===&lt;br /&gt;
&lt;br /&gt;
Parameter that allows authentication via SSH2 in the application, i.e., to use the credentials that the SSH server of the system allows.&lt;br /&gt;
&lt;br /&gt;
Can be 0 or 1.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;1&amp;quot; - actives this option.&lt;br /&gt;
* &amp;quot;0&amp;quot; - disables this option (will require to define user and password).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== LOGIN ===&lt;br /&gt;
&lt;br /&gt;
The username to authenticate against the application.&lt;br /&gt;
&lt;br /&gt;
Should be a string without spaces.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;cloudy&amp;quot; - this user can log-in with the password of PASSWORD.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PASSWORD ===&lt;br /&gt;
&lt;br /&gt;
The password of the user defined in LOGIN.&lt;br /&gt;
&lt;br /&gt;
Should be a hash over a hash MD5 (hexadecimal), i.e., a hash of the password hash: md5(md5(&amp;quot;PASSWORD&amp;quot;)).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;46d934e0f59ff1e2272f9f5f7950e5d9&amp;quot; - the hash of the string &amp;quot;PASSWORD&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''Examples of how to generate that hash in a terminal:'''&lt;br /&gt;
&lt;br /&gt;
 $ php -r 'echo md5(md5(&amp;quot;PASSWORD&amp;quot;)).&amp;quot;\n&amp;quot;;'&lt;br /&gt;
 46d934e0f59ff1e2272f9f5f7950e5d9&lt;br /&gt;
 $ printf &amp;quot;PASSWORD&amp;quot; | md5sum | awk '{printf $1}' | md5sum | awk '{print $1}'&lt;br /&gt;
 46d934e0f59ff1e2272f9f5f7950e5d9&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PORT_SSL ===&lt;br /&gt;
&lt;br /&gt;
Port that Cloudy will use in the web interface with HTTPS (if SSL is enabled).&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;7443&amp;quot; - access to the web interface in https://IP_SERVIDOR:7443.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_packages_repository</id>
		<title>Cloudy packages repository</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_packages_repository"/>
				<updated>2015-09-15T16:44:15Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot;'''''Note: this article may be outdated and should be revised. Be careful if you try to follow this guide, and better if you ask in the mailing lists first.'''''    == Upload ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''''Note: this article may be outdated and should be revised. Be careful if you try to follow this guide, and better if you ask in the mailing lists first.'''''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Upload packages to Cloudy software repository (Clommunity project) ==&lt;br /&gt;
&lt;br /&gt;
We are ready to upload packages to the Cloudy public repository http://repo.clommunity-project.eu.&lt;br /&gt;
&lt;br /&gt;
Here we request public keys to allow to upload packages and sign them. You can for sure, edit the scripts and change the paths to your needs.&lt;br /&gt;
&lt;br /&gt;
The repository is auto-signed now with a repository key name &amp;quot;gcodis Distro Development Team&amp;quot;, more info in the repository itself: http://repo.clommunity-project.eu. Auto-signing prevents that the repository remain not signed if anyone uploads unsigned packages. One signature for the repository, which is added in the client side to allow the installation of the distro, and another signature which depends on the maintainer or developer for signing the package are used. Each developer is responsible to maintain her keys safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Public keys ===&lt;br /&gt;
&lt;br /&gt;
To upload packages we need to get '''your''' public keys:&lt;br /&gt;
&lt;br /&gt;
* The '''ID of the GPG public key, uploaded to gpg.mit.edu'''. With this key you will sign the uploads.&lt;br /&gt;
* The '''public SSH key''', to access to upload packages. Needed to access to the remote repository machine.&lt;br /&gt;
&lt;br /&gt;
The packages are uploaded to the unstable branch by default (use the package changelog for that). We use the &amp;lt;code&amp;gt;dput&amp;lt;/code&amp;gt; Debian tool to upload packages and sign them. The repository is auto-signed with another key.&lt;br /&gt;
&lt;br /&gt;
You can '''send''' the public keys or IDs to the project mailing list ''clommunity-wp4''. This way we have access to public keys when required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
&lt;br /&gt;
The provided configuration file is:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.dput.cf&amp;lt;/code&amp;gt; is a configuration file which have to be copied to your home directory as &amp;lt;code&amp;gt;~/.dput.cf&amp;lt;/code&amp;gt;. Used for uploading packages with the &amp;lt;code&amp;gt;dput&amp;lt;/code&amp;gt; Debian tool.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 [repo.clommunity-project.eu]&lt;br /&gt;
 fqdn = repo.clommunity-project.eu&lt;br /&gt;
 method = scp&lt;br /&gt;
 login = repo&lt;br /&gt;
 incoming = /var/www/debian/mini-dinstall/incoming&lt;br /&gt;
 post_upload_command = ssh repo@repo.clommunity-project.eu &amp;quot;mini-dinstall -b&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Building packages ===&lt;br /&gt;
&lt;br /&gt;
Take a look to some manners to build packages at http://www.debian.org/doc/manuals/maint-guide/build.en.html.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Uploading packages ===&lt;br /&gt;
&lt;br /&gt;
You can use the &amp;lt;code&amp;gt;dput&amp;lt;/code&amp;gt; command in the following manner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 $ dput repo.clommunity-project.eu cloudy-base_0.1.3.5_i386.changes&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember to save the previous &amp;lt;code&amp;gt;~/.dput.cf&amp;lt;/code&amp;gt; file in your &amp;lt;code&amp;gt;$HOME&amp;lt;/code&amp;gt; dir.&lt;br /&gt;
&lt;br /&gt;
It's important to write the repository name ''(repo.clommunity-project.eu)''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Continuous improvements ===&lt;br /&gt;
&lt;br /&gt;
The repository is improving to better working when needed to give a better service.&lt;br /&gt;
&lt;br /&gt;
Thank you by your efforts.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_Alix</id>
		<title>Cloudy Alix</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_Alix"/>
				<updated>2015-09-11T02:32:29Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot;Alix is a [https://en.wikipedia.org/wiki/Single-board_computer SBC] with an AMD (x86) processor and several input-output interfaces (serial, miniPCI, Ethernet, etc.). For that...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Alix is a [https://en.wikipedia.org/wiki/Single-board_computer SBC] with an AMD (x86) processor and several input-output interfaces (serial, miniPCI, Ethernet, etc.). For that reason is needed an operative system prepared to run with the corresponding drivers to make these interfaces work. &lt;br /&gt;
&lt;br /&gt;
''Note: this guide has been done with Debian specially prepared to work on Alix, but it is possible that with similar steps it work with another Debian based distribution.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get Debian for Alix ==&lt;br /&gt;
&lt;br /&gt;
You can [https://code.google.com/p/debian-for-alix/ download at this website] a special Debian images just ready to work in Alix boards after flashing them in a CF card.&lt;br /&gt;
&lt;br /&gt;
=== Features/services included ===&lt;br /&gt;
&lt;br /&gt;
* Read only file system, it protects against power failures and substantially increases compact flash life time.&lt;br /&gt;
&lt;br /&gt;
* Common services available on first boot:&lt;br /&gt;
** serial terminal ( 38400n8 )&lt;br /&gt;
** dnsmasq ( DNS and DHCP servers )&lt;br /&gt;
** iptables ( basic firewall rules and internet sharing )&lt;br /&gt;
** samba ( Microsoft Windows file share )&lt;br /&gt;
** cups ( print server )&lt;br /&gt;
** vsftpd ( FTP server )&lt;br /&gt;
** nginx with fastcgi ( HTTP server )&lt;br /&gt;
** minidlna ( media server )&lt;br /&gt;
** openssh ( terminal and SFTP )&lt;br /&gt;
** stunnel ( SSL engine, HTTPS support pre-configured for ''nginx'' and ''transmission'' )&lt;br /&gt;
** tinyproxy ( HTTP/HTTPS proxy server )&lt;br /&gt;
** pptpd ( VPN server, MS Windows has builtin client support )&lt;br /&gt;
** snmpd ( SNMP server )&lt;br /&gt;
** openvpn ( VPN server and client )&lt;br /&gt;
** openconnect ( VPN client, Cisco compatible )&lt;br /&gt;
** external storage automount and sharing basic web admin panel performance monitor ( on web panel )&lt;br /&gt;
&lt;br /&gt;
* Additional services available:&lt;br /&gt;
** just turned on transmission ( torrent p2p )&lt;br /&gt;
** hostapd ( wireless access point / it needs a miniPCI card or wifi usb dongle )&lt;br /&gt;
&lt;br /&gt;
* Regular system maintenance through &amp;lt;code&amp;gt;apt-get&amp;lt;/code&amp;gt;, use it to update, install and remove applications and patches.&lt;br /&gt;
&lt;br /&gt;
* Keep in mind that it's a Debian i386, so any available software for that platform can be installed, regards hardware power limitations.&lt;br /&gt;
&lt;br /&gt;
* Image files are available for download at GoogleDrive:&lt;br /&gt;
** debian-for-alix-v1.img.bz2 (debian 6 based) version 1 wiki page&lt;br /&gt;
** debian-for-alix-v2.img.bz2 (debian 6 based) version 2 wiki page&lt;br /&gt;
** debian-for-alix-v3.img.bz2 (debian 7 based) Debian basic setup, only SSH server and basic utilities, also serial terminal was prepared, but no readonly file system and other features.&lt;br /&gt;
&lt;br /&gt;
* Default configuration is:&lt;br /&gt;
&amp;lt;code&amp;gt;eth0: DHCP&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;eth1: static 172.16.210.254&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;eth2: no configuration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;user: alix (root has locked password)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Install Debian image on CF ==&lt;br /&gt;
&lt;br /&gt;
=== Identify the CF ===&lt;br /&gt;
&lt;br /&gt;
The CF card need to be formatted with ext2. Be sure what device your CF card is, otherwise you could erase your host OS. In this example the CF card was on &amp;lt;code&amp;gt;/dev/sdb&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can check it out having a look through the &amp;lt;code&amp;gt;/proc/bus/usb/devices&amp;lt;/code&amp;gt;. You should see a section with an ''S:'' line and the name of your reader, and an ''I:'' line with &amp;lt;code&amp;gt;Driver=usb-storage&amp;lt;/code&amp;gt;. If you see that, the kernel is recognizing the device.&lt;br /&gt;
&lt;br /&gt;
Install the &amp;lt;code&amp;gt;sg3-utils&amp;lt;/code&amp;gt; package if you haven't already it (on Debian: &amp;lt;code&amp;gt;apt-get install sg3-utils&amp;lt;/code&amp;gt;). To check your SCSI devices, run the command:&lt;br /&gt;
 sg_scan -i&lt;br /&gt;
&lt;br /&gt;
You should see something like this:&lt;br /&gt;
 /dev/sg0: scsi0 channel=0 id=0 lun=0 [em]  type=0&lt;br /&gt;
 eUSB      Compact Flash     5.09 [wide=0 sync=0 cmdq=0 sftre=0 pq=0x0]    &lt;br /&gt;
&lt;br /&gt;
It indicates that the “raw” SCSI device associated with your reader is &amp;lt;code&amp;gt;/dev/sg0&amp;lt;/code&amp;gt;. You can also confirm that the driver is working by looking at the file &amp;lt;code&amp;gt;/proc/scsi/scsi&amp;lt;/code&amp;gt;. Now, to determine the real SCSI device associated with your reader run the command:&lt;br /&gt;
 sg_map&lt;br /&gt;
&lt;br /&gt;
You'll see output like this:&lt;br /&gt;
 /dev/sg0  /dev/sdb&lt;br /&gt;
&lt;br /&gt;
That's it, your card reader is &amp;lt;code&amp;gt;/dev/sdb&amp;lt;/code&amp;gt;. The first (and almost certainly only) partition is &amp;lt;code&amp;gt;/dev/sdb1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Copy image to CF ===&lt;br /&gt;
&lt;br /&gt;
To install Debian on the CF card you can do it with the following command:&lt;br /&gt;
 bzcat debian-for-alix-v3.img.bz2 | dd of=/dev/sdb bs=16k&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Install Cloudy ==&lt;br /&gt;
&lt;br /&gt;
To install Cloudy you can follow the instructions to [[Cloudy_in_Debian|convert a plain Debian installation in Cloudy]] by adding the system the specific files and tools of the distribution.&lt;br /&gt;
&lt;br /&gt;
We call it &amp;quot;cloudynize&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We recommend to use a script to automate the process. You can know how to in the [[cloudynize|wiki page that explains how to &amp;quot;cloudynize&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_Beaglebone</id>
		<title>Cloudy Beaglebone</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_Beaglebone"/>
				<updated>2015-09-10T20:20:45Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot;Beaglebone is a [https://en.wikipedia.org/wiki/Single-board_computer SBC] with an ARM processor and several input-output interfaces. For that reason is needed an operative sys...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Beaglebone is a [https://en.wikipedia.org/wiki/Single-board_computer SBC] with an ARM processor and several input-output interfaces. For that reason is needed an operative system prepared to run on an ARM architecture and with the corresponding drivers to make these interfaces work. &lt;br /&gt;
&lt;br /&gt;
''Note: this guide has been done with Ubuntu distribution, but it is possible that with the same steps it work with another Debian based distribution.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Install the base system  ==&lt;br /&gt;
&lt;br /&gt;
* Insert the microSD Card into your computer and observe which device it registers as by typing ls /dev/sd. If you are uncertain, remove the microSD Card and the entry should go away. Once you know which device your microSD Card is, follow the instructions below replacing /dev/sdX with the name of the microSD Card in your system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Begin partitioning the microSD card by typing &amp;lt;code&amp;gt;fdisk /dev/sdX&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Initialize a new partition table by selecting &amp;lt;code&amp;gt;o&amp;lt;/code&amp;gt;, then verify is empty by selecting &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Create a boot partition by selecting &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; ''(new)'', then &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; ''(primary)'', and &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; to specify the first partition. Press ''enter'' to accept the default first sector and specify &amp;lt;code&amp;gt;4095&amp;lt;/code&amp;gt; for the last sector.&lt;br /&gt;
# Change the partition type to FAT16 by selecting &amp;lt;code&amp;gt;t&amp;lt;/code&amp;gt; ''(type)'' and &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt; for ''‘W95 FAT16 (LBA)’''.&lt;br /&gt;
# Set the partition bootable by selecting &amp;lt;code&amp;gt;a&amp;lt;/code&amp;gt; then &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Next, create the data partition for the root filesystem by selecting &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; for ''(new)'', then &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; ''(primary)'', and &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; to specify the second partition. Accept the default values for the first and last sectors by pressing ''enter'' twice.&lt;br /&gt;
# Press &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; to ‘print’ the partition table.&lt;br /&gt;
# Finally, commit the changes by selecting &amp;lt;code&amp;gt;w&amp;lt;/code&amp;gt; to ''write'' the partition table and exit ''fdisk''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Continue to format the partitions and to install the boot system and the root system.&lt;br /&gt;
# Format partition 1 as FAT by typing &amp;lt;code&amp;gt;mkfs.vfat /dev/sdX1&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Format partition 2 as ext4 by typing &amp;lt;code&amp;gt;mkfs.ext4 /dev/sdX2&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Install ''u-boot'' to the microSD Card.&lt;br /&gt;
 wget http://s3.armhf.com/dist/bone/bone-uboot.tar.xz&lt;br /&gt;
 mkdir boot&lt;br /&gt;
 mount /dev/sdX1 boot&lt;br /&gt;
 tar xJvf bone-uboot.tar.xz -C boot&lt;br /&gt;
 umount boot&lt;br /&gt;
# Install the desired root filesystem to the microSD card (Ubuntu Trusty in this example).&lt;br /&gt;
 wget http://s3.armhf.com/dist/bone/ubuntu-trusty-14.04-rootfs-3.14.4.1-bone-armhf.com.tar.xz&lt;br /&gt;
 mkdir rootfs&lt;br /&gt;
 mount /dev/sdX2 rootfs&lt;br /&gt;
 tar xJvf ubuntu-trusty-14.04-rootfs-3.14.4.1-bone-armhf.com.tar.xz -C rootfs&lt;br /&gt;
 umount rootfs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The microSD Card is now ready to boot. Note that for ubuntu installations, the login userid is ''ubuntu'' and the password is ''ubuntu''.&lt;br /&gt;
&lt;br /&gt;
''Tip: the package cache has been flushed to reduce the size of the images. Run &amp;lt;code&amp;gt;apt-get update&amp;lt;/code&amp;gt; after boot to update the package cache, then run &amp;lt;code&amp;gt;apt-get upgrade&amp;lt;/code&amp;gt; to ensure the latest updates are installed.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Install Cloudy ==&lt;br /&gt;
&lt;br /&gt;
To install Cloudy you can follow the instructions to [[Cloudy_in_Debian|convert a plain Debian installation in Cloudy]] by adding the system the specific files and tools of the distribution.&lt;br /&gt;
&lt;br /&gt;
We call it &amp;quot;cloudynize&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We recommend to use a script to automate the process. You can know how to in the [[cloudynize|wiki page that explains how to &amp;quot;cloudynize&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_Raspberry_Pi</id>
		<title>Cloudy Raspberry Pi</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_Raspberry_Pi"/>
				<updated>2015-09-10T18:00:16Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Raspberry Pi is a tiny and affordable computer as large as a credit card, made mainly to be used for educational purposes and in small projects.&lt;br /&gt;
&lt;br /&gt;
This board has an ARM processor and several input-output interfaces; video, sound, Ethernet, USB, GPIO, etc. For that reason is needed an operative system prepared to run on an ARM architecture and with the corresponding drivers to make these interfaces work.&lt;br /&gt;
&lt;br /&gt;
In our case, to install Cloudy, the Raspberry Pi will be prepared with an already adapted distribution based in Debian like it's Raspbian, and once it is done we will &amp;quot;cloudynize&amp;quot; it to add all the particular content of Cloudy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''Note:''' this guide, as well as the different Cloudy installation tests, has been done with the Raspbian O.S.; but it is possible that with the same steps it work with another Debian based distribution.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Download Raspbian ==&lt;br /&gt;
&lt;br /&gt;
Go to the [https://www.raspberrypi.org/downloads/ official website] and download the ISO image with the operating system you will use as a base.&lt;br /&gt;
&lt;br /&gt;
Alternatively a Raspbian variant can be used, the [http://sirlagz.net/2013/07/19/raspbian-server-edition-2-5/ Raspbian Server Edition], which is already prepared without the unneeded packages (graphical system, sound, etc.) in the use of the Raspberry Pi as a server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Install and configure Raspbian ==&lt;br /&gt;
&lt;br /&gt;
Write the image in an SD card. Depending on the operating system of your PC you can follow one of these guides to write ISO images.&lt;br /&gt;
&lt;br /&gt;
* [http://www.raspberrypi.org/documentation/installation/installing-images/linux.md Linux]&lt;br /&gt;
* [http://www.raspberrypi.org/documentation/installation/installing-images/mac.md Mac OS]&lt;br /&gt;
* [http://www.raspberrypi.org/documentation/installation/installing-images/windows.md Windows]&lt;br /&gt;
&lt;br /&gt;
Now insert the card and power on the board to start the configuration process with the &amp;lt;code&amp;gt;raspi-config&amp;lt;/code&amp;gt; tool.&lt;br /&gt;
&lt;br /&gt;
Basically it's recommended to do:&lt;br /&gt;
# Expand the file system to use the whole SD storage space.&lt;br /&gt;
# Change the password of the '''pi''' user (the system default one).&lt;br /&gt;
# Change the localization if another language is wanted, the timezone and the keyboard layout.&lt;br /&gt;
# In the advanced options; enable the SSH server, change the hostname and update the &amp;lt;code&amp;gt;raspi-config&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you want to do some more changes, you can find more information in the [https://www.raspberrypi.org/documentation/configuration/raspi-config.md raspi-config documentation].&lt;br /&gt;
&lt;br /&gt;
We won't extend more to explain how to install and to configure Raspbian because is widely documented in the Web.&lt;br /&gt;
&lt;br /&gt;
=== Additional options ===&lt;br /&gt;
&lt;br /&gt;
As it's commented above, there is a variant of Raspbian customized to work as a server, deleting all the unneeded packages. This version should work like the original Raspbian, but it's recommended to adapt the system just after the installation manually or automating it with the ''script'' that uninstalls the packages to leave the system like the Rasbian Server Edition.&lt;br /&gt;
&lt;br /&gt;
You can find more info and download that script at [http://sirlagz.net/2013/08/03/raspbian-server-edition-scripts/ this website].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Install Cloudy ==&lt;br /&gt;
&lt;br /&gt;
To install Cloudy you can follow the instructions to [[Cloudy_en_Debian|convert a plain Debian installation in Cloudy]] by adding the system the specific files and tools of the distribution.&lt;br /&gt;
&lt;br /&gt;
We call it &amp;quot;cloudynize&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We recommend to use a script to automate the process. You can know how to in the [[cloudynize|wiki page that explains how to &amp;quot;cloudynize&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_Raspberry_Pi</id>
		<title>Cloudy Raspberry Pi</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_Raspberry_Pi"/>
				<updated>2015-09-10T17:56:33Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Raspberry Pi is a tiny and affordable computer as large as a credit card, made mainly to be used for educational purposes and in small projects.&lt;br /&gt;
&lt;br /&gt;
This board has an ARM processor and several input-output interfaces; video, sound, Ethernet, USB, GPIO, etc. For that reason is needed an operative system prepared to run on an ARM architecture and with the corresponding drivers to make these interfaces work.&lt;br /&gt;
&lt;br /&gt;
In our case, to install Cloudy, the Raspberry Pi will be prepared with an already adapted distribution based in Debian like it's Raspbian, and once it is done we will &amp;quot;cloudynize&amp;quot; it to add all the particular content of Cloudy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''Note:''' this guide, as well as the different Cloudy installation tests, has been done with the Raspbian O.S.; but it is possible that with the same steps it work with another Debian based distribution.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Download Raspbian ==&lt;br /&gt;
&lt;br /&gt;
Go to the [https://www.raspberrypi.org/downloads/ official website] and download the ISO image with the operating system you will use as a base.&lt;br /&gt;
&lt;br /&gt;
Alternatively a Raspbian variant can be used, the [http://sirlagz.net/2013/07/19/raspbian-server-edition-2-5/ Raspbian Server Edition], which is already prepared without the unneeded packages (graphical system, sound, etc.) in the use of the Raspberry Pi as a server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Install and configure Raspbian ==&lt;br /&gt;
&lt;br /&gt;
Write the image in an SD card. Depending on the operating system of your PC you can follow one of these guides to write ISO images.&lt;br /&gt;
&lt;br /&gt;
* [http://www.raspberrypi.org/documentation/installation/installing-images/linux.md Linux]&lt;br /&gt;
* [http://www.raspberrypi.org/documentation/installation/installing-images/mac.md Mac OS]&lt;br /&gt;
* [http://www.raspberrypi.org/documentation/installation/installing-images/windows.md Windows]&lt;br /&gt;
&lt;br /&gt;
Now insert the card and power on the board to start the configuration process with the &amp;lt;code&amp;gt;raspi-config&amp;lt;/code&amp;gt; tool.&lt;br /&gt;
&lt;br /&gt;
Basically it's recommended to do:&lt;br /&gt;
# Expand the file system to use the whole SD storage space.&lt;br /&gt;
# Change the password of the '''pi''' user (the system default one).&lt;br /&gt;
# Change the localization if another language is wanted, the timezone and the keyboard layout.&lt;br /&gt;
# In the advanced options; enable the SSH server, change the hostname and update the &amp;lt;code&amp;gt;raspi-config&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you want to do some more changes, you can find more information in the [https://www.raspberrypi.org/documentation/configuration/raspi-config.md raspi-config documentation].&lt;br /&gt;
&lt;br /&gt;
We won't extend more to explain how to install and to configure Raspbian because is widely documented in the Web.&lt;br /&gt;
&lt;br /&gt;
=== Additional options ===&lt;br /&gt;
&lt;br /&gt;
As it's commented above, there is a variant of Raspbian customized to work as a server, deleting all the unneeded packages. This version should work like the original Raspbian, but it's recommended to adapt the system just after the installation manually or automating it with the ''script'' that uninstalls the packages to leave the system like the Rasbian Server Edition.&lt;br /&gt;
&lt;br /&gt;
You can find more info and download that script at [http://sirlagz.net/2013/08/03/raspbian-server-edition-scripts/ this website].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Install Cloudy ==&lt;br /&gt;
&lt;br /&gt;
To install Cloudy you can follow the instructions to [[Cloudy_en_Debian|convert a plain Debian installation in Cloudy]] by adding the system the specific files and tools of the Cloudy distribution.&lt;br /&gt;
&lt;br /&gt;
We call it &amp;quot;cloudynize&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We recommend to use a script to automate the process, you can know how to in the [[cloudynize|wiki page that explains how to cloudynize]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_in_Debian</id>
		<title>Cloudy in Debian</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_in_Debian"/>
				<updated>2015-09-10T17:41:39Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;You can convert a plain Debian installation into Cloudy following these steps:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. Enter via SSH as a root user (or once logged in) or execute the next commands with ''sudo'' tool.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
2. Update date from server by installing a NTP client ''(optional)''.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ntp&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
3. Add Debian backports, Clommunity and Guifi repositories.&lt;br /&gt;
* Debian backports:&lt;br /&gt;
 echo &amp;quot;deb http://ftp.debian.org/debian wheezy-backports main contrib&amp;quot; &amp;gt; /etc/apt/sources.list.d/backports.list &lt;br /&gt;
* Clommunity repository:&lt;br /&gt;
 echo &amp;quot;deb http://repo.clommunity-project.eu/debian unstable/&amp;quot; &amp;gt; /etc/apt/sources.list.d/cloudy.list &lt;br /&gt;
 gpg --keyserver pgpkeys.mit.edu --recv-key A59C5DC8 &amp;amp;&amp;amp; gpg --export --armor A59C5DC8 | apt-key add - &lt;br /&gt;
* Guifi repository:&lt;br /&gt;
 echo &amp;quot;deb http://serveis.guifi.net/debian guifi/&amp;quot; &amp;gt; /etc/apt/sources.list.d/serveis.list &lt;br /&gt;
 gpg --keyserver pgpkeys.mit.edu --recv-key 2E484DAB &amp;amp;&amp;amp; gpg --export --armor 2E484DAB | apt-key add -&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
4. Install some Debian packages.&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get install -y openssh-server openssh-client getinconf-client curl unzip make avahi-utils tahoe-lafs mysql-server python2.7 g++ make checkinstall openjdk-6-jre locales php5 libssh2-php libapache2-mod-encoding &lt;br /&gt;
&lt;br /&gt;
'''''Note''': If this error appears: &amp;quot;Error W: GPG error: http://ftp.debian.org wheezy-backports InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY8B48AD6246925553&amp;quot; use this command:&lt;br /&gt;
 apt-get --allow-unauthenticated upgrade&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5. Install the Cloudy non-Debian packages.&lt;br /&gt;
 curl &amp;quot;https://raw.githubusercontent.com/Clommunity/lbmake/master/hooks/getinconf-client.chroot&amp;quot; | sh -&lt;br /&gt;
 curl &amp;quot;https://raw.githubusercontent.com/Clommunity/lbmake/master/hooks/avahi-ps.chroot&amp;quot; | sh -&lt;br /&gt;
 curl &amp;quot;https://raw.githubusercontent.com/Clommunity/lbmake/master/hooks/cDistro.chroot&amp;quot; | sh -&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
g. Reboot.&lt;br /&gt;
&lt;br /&gt;
After this, you can browse the web user interface at http://device_IP:7000&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_in_Debian</id>
		<title>Cloudy in Debian</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_in_Debian"/>
				<updated>2015-09-10T17:33:26Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;You can convert a plain Debian installation into Cloudy following these steps:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. Enter via SSH as a root user (or once logged in) or execute the next commands with ''sudo'' tool.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
2. Update date from server by installing a ntp client ''(optional)''.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ntp&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
3. Add Debian backports, Clommunity and Guifi repositories.&lt;br /&gt;
* Debian Backports:&lt;br /&gt;
 echo &amp;quot;deb http://ftp.debian.org/debian wheezy-backports main contrib&amp;quot; &amp;gt; /etc/apt/sources.list.d/backports.list &lt;br /&gt;
* Clommunity repository&lt;br /&gt;
 echo &amp;quot;deb http://repo.clommunity-project.eu/debian unstable/&amp;quot; &amp;gt; /etc/apt/sources.list.d/cloudy.list &lt;br /&gt;
 gpg --keyserver pgpkeys.mit.edu --recv-key A59C5DC8 &amp;amp;&amp;amp; gpg --export --armor A59C5DC8 | apt-key add - &lt;br /&gt;
* Guifi repository&lt;br /&gt;
 echo &amp;quot;deb http://serveis.guifi.net/debian guifi/&amp;quot; &amp;gt; /etc/apt/sources.list.d/serveis.list &lt;br /&gt;
 gpg --keyserver pgpkeys.mit.edu --recv-key 2E484DAB &amp;amp;&amp;amp; gpg --export --armor 2E484DAB | apt-key add -&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
4. Install some Debian packages.&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get install -y openssh-server openssh-client getinconf-client curl unzip make avahi-utils tahoe-lafs mysql-server python2.7 g++ make checkinstall openjdk-6-jre locales php5 libssh2-php libapache2-mod-encoding &lt;br /&gt;
&lt;br /&gt;
'''''Note''': If this error appears: ·Error W: GPG error: http://ftp.debian.org wheezy-backports InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY8B48AD6246925553&amp;quot; use this command:&lt;br /&gt;
 apt-get --allow-unauthenticated upgrade&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5. Install the Cloudy non-Debian packages.&lt;br /&gt;
 curl &amp;quot;https://raw.githubusercontent.com/Clommunity/lbmake/master/hooks/getinconf-client.chroot&amp;quot; | sh -&lt;br /&gt;
 curl &amp;quot;https://raw.githubusercontent.com/Clommunity/lbmake/master/hooks/avahi-ps.chroot&amp;quot; | sh -&lt;br /&gt;
 curl &amp;quot;https://raw.githubusercontent.com/Clommunity/lbmake/master/hooks/cDistro.chroot&amp;quot; | sh -&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
g. Reboot.&lt;br /&gt;
&lt;br /&gt;
After this, you can browse the web user interface at http://device_IP:7000&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_in_Debian</id>
		<title>Cloudy in Debian</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_in_Debian"/>
				<updated>2015-09-10T17:32:40Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot;You can convert a plain Debian installation into Cloudy following these steps:   1. Enter via SSH as a root user (or once logged in) or execute the next commands with ''sudo''...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;You can convert a plain Debian installation into Cloudy following these steps:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. Enter via SSH as a root user (or once logged in) or execute the next commands with ''sudo'' tool.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
2. Update date from server by installing a ntp client (optional).&lt;br /&gt;
&lt;br /&gt;
 apt-get install ntp&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
3. Add Debian backports, Clommunity and Guifi repositories.&lt;br /&gt;
* Debian Backports:&lt;br /&gt;
 echo &amp;quot;deb http://ftp.debian.org/debian wheezy-backports main contrib&amp;quot; &amp;gt; /etc/apt/sources.list.d/backports.list &lt;br /&gt;
* Clommunity repository&lt;br /&gt;
 echo &amp;quot;deb http://repo.clommunity-project.eu/debian unstable/&amp;quot; &amp;gt; /etc/apt/sources.list.d/cloudy.list &lt;br /&gt;
 gpg --keyserver pgpkeys.mit.edu --recv-key A59C5DC8 &amp;amp;&amp;amp; gpg --export --armor A59C5DC8 | apt-key add - &lt;br /&gt;
* Guifi repository&lt;br /&gt;
 echo &amp;quot;deb http://serveis.guifi.net/debian guifi/&amp;quot; &amp;gt; /etc/apt/sources.list.d/serveis.list &lt;br /&gt;
 gpg --keyserver pgpkeys.mit.edu --recv-key 2E484DAB &amp;amp;&amp;amp; gpg --export --armor 2E484DAB | apt-key add -&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
4. Install some Debian packages.&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get install -y openssh-server openssh-client getinconf-client curl unzip make avahi-utils tahoe-lafs mysql-server python2.7 g++ make checkinstall openjdk-6-jre locales php5 libssh2-php libapache2-mod-encoding &lt;br /&gt;
&lt;br /&gt;
'''''Note''': If this error appears: ·Error W: GPG error: http://ftp.debian.org wheezy-backports InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY8B48AD6246925553&amp;quot; use this command:&lt;br /&gt;
 apt-get --allow-unauthenticated upgrade&lt;br /&gt;
''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5. Install non-Debian packages.&lt;br /&gt;
 curl &amp;quot;https://raw.githubusercontent.com/Clommunity/lbmake/master/hooks/getinconf-client.chroot&amp;quot; | sh -&lt;br /&gt;
 curl &amp;quot;https://raw.githubusercontent.com/Clommunity/lbmake/master/hooks/avahi-ps.chroot&amp;quot; | sh -&lt;br /&gt;
 curl &amp;quot;https://raw.githubusercontent.com/Clommunity/lbmake/master/hooks/cDistro.chroot&amp;quot; | sh -&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
g. Reboot.&lt;br /&gt;
&lt;br /&gt;
After this, you can browse the web user interface at http://device_IP:7000&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_Raspberry_PI</id>
		<title>Cloudy Raspberry PI</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_Raspberry_PI"/>
				<updated>2015-07-22T01:00:21Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Redirected page to Cloudy Raspberry Pi&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Cloudy_Raspberry_Pi]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_Raspberry_Pi</id>
		<title>Cloudy Raspberry Pi</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_Raspberry_Pi"/>
				<updated>2015-07-22T00:30:26Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot;The Raspberry Pi is a tiny and affordable computer as large as a credit card, made mainly to be used for educational purposes and in small projects.  This board has an ARM pro...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Raspberry Pi is a tiny and affordable computer as large as a credit card, made mainly to be used for educational purposes and in small projects.&lt;br /&gt;
&lt;br /&gt;
This board has an ARM processor and several input-output interfaces; video, sound, Ethernet, USB, GPIO, etc. For that reason is needed an operative system prepared to run on an ARM architecture and with the corresponding drivers to make these interfaces work.&lt;br /&gt;
&lt;br /&gt;
In our case, to install Cloudy, the Raspberry Pi will be prepared with an already adapted distribution based in Debian like it's Raspbian, and once it is done we will &amp;quot;cloudynize&amp;quot; it to add all the particular content of Cloudy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''Note:''' this guide, as well as the different Cloudy installation tests, has been done with the Raspbian O.S.; but it is possible that with the same steps it work with another Debian based distribution.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Download Raspbian ==&lt;br /&gt;
&lt;br /&gt;
Go to the [https://www.raspberrypi.org/downloads/ official website] and download the ISO image with the operating system you will use as a base.&lt;br /&gt;
&lt;br /&gt;
Alternatively a Raspbian variant can be used, the [http://sirlagz.net/2013/07/19/raspbian-server-edition-2-5/ Raspbian Server Edition], which is already prepared without the unneeded packages (graphical system, sound, etc.) in the use of the Raspberry Pi as a server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Install and configure Raspbian ==&lt;br /&gt;
&lt;br /&gt;
Write the image in an SD card. Depending on the operating system of your PC you can follow one of these guides to write ISO images.&lt;br /&gt;
&lt;br /&gt;
* [http://www.raspberrypi.org/documentation/installation/installing-images/linux.md Linux]&lt;br /&gt;
* [http://www.raspberrypi.org/documentation/installation/installing-images/mac.md Mac OS]&lt;br /&gt;
* [http://www.raspberrypi.org/documentation/installation/installing-images/windows.md Windows]&lt;br /&gt;
&lt;br /&gt;
Now insert the card and power on the board to start the configuration process with the &amp;lt;code&amp;gt;raspi-config&amp;lt;/code&amp;gt; tool.&lt;br /&gt;
&lt;br /&gt;
Basically it's recommended to do:&lt;br /&gt;
# Expand the file system to use the whole SD storage space.&lt;br /&gt;
# Change the password of the '''pi''' user (the system default one).&lt;br /&gt;
# Change the localization if another language is wanted, the timezone and the keyboard layout.&lt;br /&gt;
# In the advanced options; enable the SSH server, change the hostname and update the &amp;lt;code&amp;gt;raspi-config&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you want to do some more changes, you can find more information in the [https://www.raspberrypi.org/documentation/configuration/raspi-config.md raspi-config documentation].&lt;br /&gt;
&lt;br /&gt;
We won't extend more to explain how to install and to configure Raspbian because is widely documented in the Web.&lt;br /&gt;
&lt;br /&gt;
=== Additional options ===&lt;br /&gt;
&lt;br /&gt;
As it's commented above, there is a variant of Raspbian customized to work as a server, deleting all the unneeded packages. This version should work like the original Raspbian, but it's recommended to adapt the system just after the installation manually or automating it with the ''script'' that uninstalls the packages to leave the system like the Rasbian Server Edition.&lt;br /&gt;
&lt;br /&gt;
You can find more info and download that script at [http://sirlagz.net/2013/08/03/raspbian-server-edition-scripts/ this website].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Install Cloudy ==&lt;br /&gt;
&lt;br /&gt;
To install Cloudy we &amp;quot;cloudynize&amp;quot; the system to add it the specific files and tools of the Cloudy distribution.&lt;br /&gt;
&lt;br /&gt;
To do it, you can follow the instructions of the [[cloudynize|wiki page that explains how to cloudynize a Debian system]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_in_client_node</id>
		<title>Cloudy in client node</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_in_client_node"/>
				<updated>2015-07-17T15:57:59Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot;Cloudy uses a system to publish and search services, to share them with the other Cloudys. For this purpose, actually [https://www.serfdom.io/ Serf] is used.  This software op...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Cloudy uses a system to publish and search services, to share them with the other Cloudys. For this purpose, actually [https://www.serfdom.io/ Serf] is used.&lt;br /&gt;
&lt;br /&gt;
This software opens a TCP port in the server (Cloudy) to listen to petitions and to be able to communicate to others.&lt;br /&gt;
&lt;br /&gt;
Therefore, some additional steps are needed to allow a Cloudy installed in a client node to interact to other Cloudys:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. Know the node’s public IP address (10.x.x.x); not the one assigned to Cloudy but the IP assigned to the client node.&lt;br /&gt;
* You can go to the [http://guifi.net Guifi] page of your node to know what is its IP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
2. Edit a couple of files and declare the public IP of the node. You have to add the IP in the configuration files in order to allow the software to announce correctly the public IP instead the private IP.&lt;br /&gt;
* To do it, with the '''''root''''' user, write in the command line the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@cloudy:~# echo &amp;quot;ADVERTISE_IP=10.x.x.x&amp;quot; &amp;gt;&amp;gt; /etc/avahi-ps-serf.conf&lt;br /&gt;
root@cloudy:~# echo &amp;quot;PUBLIC_IP=10.x.x.x&amp;quot; &amp;gt;&amp;gt; /etc/getinconf-client.conf&lt;br /&gt;
root@cloudy:~# /etc/init.d/serf restart&lt;br /&gt;
&lt;br /&gt;
(where 10.x.x.x is the public IP of your node)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Exemple:'''&lt;br /&gt;
in a node with IP address 10.1.2.3 the files should be like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  /etc/avahi-ps-serf.conf&lt;br /&gt;
SERF_RPC_ADDR=127.0.0.1:7373&lt;br /&gt;
SERF_BIND=5000&lt;br /&gt;
SERF_JOIN=10.139.40.82:5000&lt;br /&gt;
ADVERTISE_IP=10.1.2.3&lt;br /&gt;
&lt;br /&gt;
  /etc/getinconf-client.conf &lt;br /&gt;
#!/bin/sh&lt;br /&gt;
# Automatically generate file&lt;br /&gt;
GTC_SERVER_URL=http://10.139.40.84/index.php&lt;br /&gt;
NETWORK_NAME=demo&lt;br /&gt;
NETWORK_KEY=demo&lt;br /&gt;
INTERNAL_DEV=eth0&lt;br /&gt;
# PORT=665&lt;br /&gt;
# GETINCONF_IGNORE=1&lt;br /&gt;
GETINCONF_IGNORE=1&lt;br /&gt;
PUBLIC_IP=10.1.2.3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Do a port forwarding for the port 5000 (Serf). And if you want more services you will have to redirect (forward) the port of each service.&lt;br /&gt;
* The configuration to do that depends on the device you have.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_64bits</id>
		<title>Cloudy 64bits</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_64bits"/>
				<updated>2015-05-13T13:52:05Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Actually it is only available the 32 bits version, however you can create the 64 bits version by following these steps:&lt;br /&gt;
&lt;br /&gt;
First, download the generation system (or image builder):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install build-essential live-build imagemagick curl debootstrap git unzip &lt;br /&gt;
git clone http://dev.cloudy.community/guifi.net/cloudy-image-builder.git&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you have to do a little modification to the Makefile file: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ARCH ?= amd64&lt;br /&gt;
FLAVOUR ?= amd64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, you can build the image with this command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo make&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once the image has been created, you have a 64 bits version of Cloudy in ./devel/binary.hybrid.iso &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Otherwise you can &amp;quot;Cloudynize&amp;quot; a 64 bits Debian or Debian based system to turn it into Cloudy.&lt;br /&gt;
&lt;br /&gt;
Read how to in the [[Cloudynize]] wiki page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudynize</id>
		<title>Cloudynize</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudynize"/>
				<updated>2015-05-13T12:56:27Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot;An alternative method to install Cloudy is modifying a Debian GNU/Linux system, or a Debian based, by applying a script which turns the system into a Cloudy.  To do this you c...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An alternative method to install Cloudy is modifying a Debian GNU/Linux system, or a Debian based, by applying a script which turns the system into a Cloudy.&lt;br /&gt;
&lt;br /&gt;
To do this you can run the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/Clommunity/cloudynitzar &amp;amp;&amp;amp; cd cloudynitzar&lt;br /&gt;
chmod +x cloudynitzar.sh&lt;br /&gt;
sudo ./cloudynitzar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_64bits</id>
		<title>Cloudy 64bits</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_64bits"/>
				<updated>2015-05-13T12:44:23Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Actually it is only available the 32 bits version, however you can create the 64 bits version by following these steps:&lt;br /&gt;
&lt;br /&gt;
First, download the generation system (or image builder):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install build-essential live-build imagemagick curl debootstrap git unzip &lt;br /&gt;
git clone http://dev.cloudy.community/guifi.net/cloudy-image-builder.git&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you have to do a little modification to the Makefile file: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ARCH ?= amd64&lt;br /&gt;
FLAVOUR ?= amd64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, you can build the image with this command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo make&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once the image has been created, you have a 64 bits version of Cloudy in ./devel/binary.hybrid.iso &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_64bits</id>
		<title>Cloudy 64bits</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_64bits"/>
				<updated>2015-05-13T12:44:13Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot;Actually it is only available the 32 bits version, however you can create the 64 bits version by following these steps:  First, download the generation system (or image builde...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Actually it is only available the 32 bits version, however you can create the 64 bits version by following these steps:&lt;br /&gt;
&lt;br /&gt;
First, download the generation system (or image builder):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install build-essential live-build imagemagick curl debootstrap git unzip &lt;br /&gt;
git clone http://dev.cloudy.community/guifi.net/cloudy-image-builder.git&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you have to do a little modification to the Makefile file: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ARCH ?= amd64&lt;br /&gt;
FLAVOUR ?= amd64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, you can build the image with this command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo make&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once the image has been created, you have a 64 bits version of Cloudy in ./devel/binary.hybrid.iso &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoria:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/What_is_Cloudy</id>
		<title>What is Cloudy</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/What_is_Cloudy"/>
				<updated>2015-05-13T12:25:35Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:clommunity-logo.png|right|100px]]&lt;br /&gt;
[[File:Logo_guifi.svg|right|100px]]&lt;br /&gt;
&lt;br /&gt;
Cloudy &amp;lt;ref name=&amp;quot;cloudy&amp;quot;&amp;gt;Cloudy: http://wiki.clommunity-project.eu/soft:cloudservices&amp;lt;/ref&amp;gt; is a distribution based in Debian GNU/Linux &amp;lt;ref name=&amp;quot;debian&amp;quot;&amp;gt;Debian GNU/Linux: http://debian.org&amp;lt;/ref&amp;gt; developed under the CLOMMUNITY european research project.&amp;lt;ref name=&amp;quot;clommunity&amp;quot;&amp;gt;CLOMMUNITY project: http://clommunity-project.eu&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This distribution, inspired in the idea of the old [[Guinux]] &amp;lt;ref name=&amp;quot;guinux&amp;quot;&amp;gt;Guinux: http://guifi.net/node/29320&amp;lt;/ref&amp;gt;, facilitates the deployment and the management of cloud services&amp;lt;ref name=&amp;quot;cloud-services&amp;quot;&amp;gt;Cloud computing: http://en.wikipedia.org/wiki/Cloud_computing&amp;lt;/ref&amp;gt;, as well as sharing them. Particulary intended to the community network&amp;lt;ref name=&amp;quot;CN&amp;quot;&amp;gt;Community networks: http://en.wikipedia.org/wiki/Community_network&amp;lt;/ref&amp;gt; users.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Prior to the general adoption of cloud services&amp;lt;ref name=&amp;quot;cloud-services&amp;quot;/&amp;gt;, users of Community Networks (CNs&amp;lt;ref name=&amp;quot;CN&amp;quot;/&amp;gt;) already shared or provided services and resources to the community, however, these users were only a minority. One of the reasons identified is the technological barrier. Before providing content, users willing to share information with the community have first to take care of the technical aspects such as the deployment of a server with a set of services.&lt;br /&gt;
&lt;br /&gt;
In the past, users from the Guifi.net CN tried to overcome this problem by releasing a GNU/Linux distribution named [[Guinux]] &amp;lt;ref name=&amp;quot;guinux&amp;quot;/&amp;gt;, which provided end users an easy way of offering network services to the community (like [[Proxy_Server|HTTP proxy]], [[DNS_Server|DNS systems]] and [[Graphserver_1|MRTG graphic interfaces]]).&lt;br /&gt;
&lt;br /&gt;
The key part of the distribution was a set of scripts&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Scripting_language&amp;lt;/ref&amp;gt; that automatised the configuration process. End users were only asked for a few parameters such as their e-mail address and the node identifier. Shortly after the distribution was made available the number of end users sharing resources proliferated.&lt;br /&gt;
&lt;br /&gt;
According to that, it became clear that lowering (or removing) the technological entry barrier encouraged users to provide more services and share their resources with the community. To this end, one of the goals of the CLOMMUNITY &amp;lt;ref name=&amp;quot;clommunity&amp;quot;/&amp;gt; project is to release a GNU/Linux distribution, codenamed Cloudy, aimed at end users, to foster the transition and adoption of the Community Network cloud environment.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motivation === &lt;br /&gt;
&lt;br /&gt;
The Cloudy distributión is thought to satisfy the following requirements:&lt;br /&gt;
&lt;br /&gt;
# '''Distribution''': in order to foster services distribution amongst the Community Networks (CNs), a platform to publish and discover them is required. This way, service access does not depend on static networking deployments and is aware of the dynamically-changing conditions of CNs. The software chosen for service publishing and discovering is Avahi&amp;lt;ref name=&amp;quot;avahi&amp;quot;&amp;gt;Avahi: http://avahi.org&amp;lt;/ref&amp;gt;.&lt;br /&gt;
# '''Decentralisation''': a common network layer is required to allow all CN cloud nodes to communicate with each other directly. A good way to build it is to create a virtual Layer 2 based on a VPN&amp;lt;ref&amp;gt;Virtual Private Network: http://en.wikipedia.org/wiki/Virtual_private_network&amp;lt;/ref&amp;gt; service. Among the available options, Tinc VPN&amp;lt;ref&amp;gt;Tinc VPN: http://tinc-vpn.org&amp;lt;/ref&amp;gt; has been chosen, as it fulfills all the requirements while being easy to configure and manage. To coordinate the devices with TincVPN, a tool to automate the system deployment has been developed as part of the project. This software, named Getinconf&amp;lt;ref&amp;gt;Getinconf: https://github.com/Clommunity/getinconf/blob/master/README.md&amp;lt;/ref&amp;gt;, takes care of the TincVPN configuration process and the exchange of keys with the rest of the cloud nodes.&lt;br /&gt;
# '''User-friendliness''': to this end, a web-based management platform has been developed aimed to integrate all the installation and configuration steps for the cloud services enabled in the Cloudy distribution. A simple web interface&amp;lt;ref&amp;gt;Cloudy web interface: http://redmine.confine-project.eu/projects/getinconf&amp;lt;/ref&amp;gt; is available to the end user as an easy way of configure, administer and monitor the cloud services running in the node.&lt;br /&gt;
# '''Free, Libre, Open Source Software''': the distribution has been based on Debian GNU/Linux&amp;lt;ref name=&amp;quot;debian&amp;quot;/&amp;gt;. Apart from being one of the most popular distributions and fulfilling all the technical requirements, it has been chosen because the Debian Social Contract&amp;lt;ref&amp;gt;Debian social contract: https://www.debian.org/social_contract&amp;lt;/ref&amp;gt; safeguards and guarantees that the software will always be open and free.&lt;br /&gt;
&lt;br /&gt;
[[File:Cloudy-home.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
&lt;br /&gt;
Enter to the &amp;quot;Get started&amp;quot; section in the Cloudy website &amp;lt;ref name=&amp;quot;start&amp;quot;&amp;gt;http://cloudy.community/get_started/&amp;lt;/ref&amp;gt; to know all you need to start with Cloudy.&lt;br /&gt;
&lt;br /&gt;
There you will find:&lt;br /&gt;
* Requirements&lt;br /&gt;
* Get/compile&lt;br /&gt;
* Install&lt;br /&gt;
* Update&lt;br /&gt;
* First steps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Contents ==&lt;br /&gt;
&lt;br /&gt;
In the &amp;quot;Features&amp;quot; section &amp;lt;ref name=&amp;quot;features&amp;quot;&amp;gt;http://cloudy.community/features/&amp;lt;/ref&amp;gt; you can see all the contents/software included in the distribution. Specifically is detailed the software that can be easily managed through the web interface.&lt;br /&gt;
&lt;br /&gt;
This software is integrated by a ''plug-ins'' system. You can read more in the wiki page of [[Cloudy_plug-ins|Cloudy plug-ins]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Contributing ==&lt;br /&gt;
&lt;br /&gt;
To stay up to date or to know how to collaborate and get involved with Cloudy, enter to the &amp;quot;Contribute&amp;quot; in the website.&amp;lt;ref name=&amp;quot;contribuir&amp;quot;&amp;gt;http://cloudy.community/contribute/&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Remember that the mailing lists are in English because there are participants from different countries.&lt;br /&gt;
&lt;br /&gt;
If you want to write in Catalan or in Spanish you should add [CAT] or [ES] respectively in the subject of the mail message.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== More information ==&lt;br /&gt;
&lt;br /&gt;
You can read more in the wiki page of the [[Cloudy|Cloudy category]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
&lt;br /&gt;
* http://cloudy.community&lt;br /&gt;
* http://wiki.clommunity-project.eu/soft:cloudservices&lt;br /&gt;
* http://clommunity-project.eu&lt;br /&gt;
* http://guifi.net&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/What_is_Cloudy</id>
		<title>What is Cloudy</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/What_is_Cloudy"/>
				<updated>2015-05-12T20:08:28Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot;100px 100px  Cloudy &amp;lt;ref name=&amp;quot;cloudy&amp;quot;&amp;gt;Cloudy: http://wiki.clommunity-project.eu/soft:cloudservices&amp;lt;/ref&amp;gt; is a...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:clommunity-logo.png|right|100px]]&lt;br /&gt;
[[File:Logo_guifi.svg|right|100px]]&lt;br /&gt;
&lt;br /&gt;
Cloudy &amp;lt;ref name=&amp;quot;cloudy&amp;quot;&amp;gt;Cloudy: http://wiki.clommunity-project.eu/soft:cloudservices&amp;lt;/ref&amp;gt; is a distribution based in Debian GNU/Linux &amp;lt;ref name=&amp;quot;debian&amp;quot;&amp;gt;Debian GNU/Linux: http://debian.org&amp;lt;/ref&amp;gt; developed under the CLOMMUNITY european research project.&amp;lt;ref name=&amp;quot;clommunity&amp;quot;&amp;gt;CLOMMUNITY project: http://clommunity-project.eu&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This distribution, inspired in the idea of the old [[Guinux]] &amp;lt;ref name=&amp;quot;guinux&amp;quot;&amp;gt;Guinux: http://guifi.net/node/29320&amp;lt;/ref&amp;gt;, facilitates the deployment and the management of cloud services&amp;lt;ref name=&amp;quot;cloud-services&amp;quot;&amp;gt;Cloud computing: http://en.wikipedia.org/wiki/Cloud_computing&amp;lt;/ref&amp;gt;, as well as sharing them. Particulary intended to the community network&amp;lt;ref name=&amp;quot;CN&amp;quot;&amp;gt;Community networks: http://en.wikipedia.org/wiki/Community_network&amp;lt;/ref&amp;gt; users.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Prior to the general adoption of cloud services&amp;lt;ref name=&amp;quot;cloud-services&amp;quot;/&amp;gt;, users of Community Networks (CNs&amp;lt;ref name=&amp;quot;CN&amp;quot;/&amp;gt;) already shared or provided services and resources to the community, however, these users were only a minority. One of the reasons identified is the technological barrier. Before providing content, users willing to share information with the community have first to take care of the technical aspects such as the deployment of a server with a set of services.&lt;br /&gt;
&lt;br /&gt;
In the past, users from the Guifi.net CN tried to overcome this problem by releasing a GNU/Linux distribution named [[Guinux]] &amp;lt;ref name=&amp;quot;guinux&amp;quot;/&amp;gt;, which provided end users an easy way of offering network services to the community (like [[Proxy_Server|HTTP proxy]], [[DNS_Server|DNS systems]] and [[Graphserver_1|MRTG graphic interfaces]]).&lt;br /&gt;
&lt;br /&gt;
The key part of the distribution was a set of scripts&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Scripting_language&amp;lt;/ref&amp;gt; that automatised the configuration process. End users were only asked for a few parameters such as their e-mail address and the node identifier. Shortly after the distribution was made available the number of end users sharing resources proliferated.&lt;br /&gt;
&lt;br /&gt;
According to that, it became clear that lowering (or removing) the technological entry barrier encouraged users to provide more services and share their resources with the community. To this end, one of the goals of the CLOMMUNITY &amp;lt;ref name=&amp;quot;clommunity&amp;quot;/&amp;gt; project is to release a GNU/Linux distribution, codenamed Cloudy, aimed at end users, to foster the transition and adoption of the Community Network cloud environment.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motivation === &lt;br /&gt;
&lt;br /&gt;
The Cloudy distributión is thought to satisfy the following requirements:&lt;br /&gt;
&lt;br /&gt;
# '''Distribution''': in order to foster services distribution amongst the Community Networks (CNs), a platform to publish and discover them is required. This way, service access does not depend on static networking deployments and is aware of the dynamically-changing conditions of CNs. The software chosen for service publishing and discovering is Avahi&amp;lt;ref name=&amp;quot;avahi&amp;quot;&amp;gt;Avahi: http://avahi.org&amp;lt;/ref&amp;gt;.&lt;br /&gt;
# '''Decentralisation''': a common network layer is required to allow all CN cloud nodes to communicate with each other directly. A good way to build it is to create a virtual Layer 2 based on a VPN&amp;lt;ref&amp;gt;Virtual Private Network: http://en.wikipedia.org/wiki/Virtual_private_network&amp;lt;/ref&amp;gt; service. Among the available options, Tinc VPN&amp;lt;ref&amp;gt;Tinc VPN: http://tinc-vpn.org&amp;lt;/ref&amp;gt; has been chosen, as it fulfills all the requirements while being easy to configure and manage.&lt;br /&gt;
To coordinate the devices with TincVPN, a tool to automate the system deployment has been developed as part of the project. This software, named Getinconf&amp;lt;ref&amp;gt;Getinconf: https://github.com/Clommunity/getinconf/blob/master/README.md&amp;lt;/ref&amp;gt;, takes care of the TincVPN configuration process and the exchange of keys with the rest of the cloud nodes.&lt;br /&gt;
# '''User-friendliness''': to this end, a web-based management platform has been developed aimed to integrate all the installation and configuration steps for the cloud services enabled in the Cloudy distribution. A simple web interface&amp;lt;ref&amp;gt;Cloudy web interface: http://redmine.confine-project.eu/projects/getinconf&amp;lt;/ref&amp;gt; is available to the end user as an easy way of configure, administer and monitor the cloud services running in the node.&lt;br /&gt;
# '''Free, Libre, Open Source Software''': the distribution has been based on Debian GNU/Linux&amp;lt;ref name=&amp;quot;debian&amp;quot;/&amp;gt;. Apart from being one of the most popular distributions and fulfilling all the technical requirements, it has been chosen because the Debian Social Contract&amp;lt;ref&amp;gt;Debian social contract: https://www.debian.org/social_contract&amp;lt;/ref&amp;gt; safeguards and guarantees that the software will always be open and free.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Minimum requirements ==&lt;br /&gt;
&lt;br /&gt;
As Cloudy is based in Debian, it has the same hardware requirements.&amp;lt;ref&amp;gt;Minimum requirements: https://www.debian.org/releases/stable/i386/ch03s04.html.en&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The binary image have a set of configurations and additional packages; thus are needed arround '''450 MiB of free storage space'''.&lt;br /&gt;
Anyway, it is '''recommended''' to have '''at least 1 GiB'''.&lt;br /&gt;
&lt;br /&gt;
If you want to use some services like PeerStreamer (read below) the minimum requirements will increase, both storage, memory and processing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Getting Cloudy ==&lt;br /&gt;
&lt;br /&gt;
Actually you can obtain the Cloudy distribution by downloading an ISO image ready to burn in a CD or USB memory, or by downloading a template (LXC container&amp;lt;ref&amp;gt;Linux containers (LXC): https://linuxcontainers.org/&amp;lt;/ref&amp;gt; or OpenVZ&amp;lt;ref&amp;gt;http://openvz.org&amp;lt;/ref&amp;gt;) ready to be executed in a virtual machine.&lt;br /&gt;
&lt;br /&gt;
Alternatively you can download the source code and compile it by your own.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Downloading the image ===&lt;br /&gt;
&lt;br /&gt;
Go to the Cloudy site where image are stored:&lt;br /&gt;
&lt;br /&gt;
http://repo.clommunity-project.eu/images/&lt;br /&gt;
&lt;br /&gt;
Currently is in development and is '''only available the ''unstable'' branch'''.&lt;br /&gt;
&lt;br /&gt;
There you will find:&lt;br /&gt;
&lt;br /&gt;
* cloudy.README - List of additional packages included in the image.&lt;br /&gt;
* cloudy.container.tar.gz - Container template.&lt;br /&gt;
* cloudy.iso - ISO image&lt;br /&gt;
&lt;br /&gt;
==== Burn the ISO image (Linux) ====&lt;br /&gt;
&lt;br /&gt;
The ISO file is a live install CD image, it means that it has installation system which is executed from a removable device (CD/DVD/USB) at boot.&lt;br /&gt;
&lt;br /&gt;
You can burn it in:&lt;br /&gt;
&lt;br /&gt;
* A CD or DVD:&lt;br /&gt;
&lt;br /&gt;
 $ apt-get install xorriso&lt;br /&gt;
 $ xorriso -as cdrecord -v dev=/dev/sr0 blank=as_needed cloudy.iso&lt;br /&gt;
&lt;br /&gt;
* A USB memory:&lt;br /&gt;
&lt;br /&gt;
 $ dd if=cloudy.iso of=${USBSTICK}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Compiling ===&lt;br /&gt;
&lt;br /&gt;
In order to build or compile Cloudy some programs are needed in your machine to download the sources, generate the binaries, manipulate the ISO images, etc.&lt;br /&gt;
&lt;br /&gt;
1. Download the needed packages (example with the ''apt'' tool in the Debian based systems):&lt;br /&gt;
 sudo apt-get install build-essential live-build imagemagick curl debootstrap git unzip &lt;br /&gt;
&lt;br /&gt;
2. Download the &amp;quot;builder&amp;quot; ''LBmake'' (Live-Build Make) to create the image:&lt;br /&gt;
 git clone https://github.com/Clommunity/lbmake&lt;br /&gt;
&lt;br /&gt;
3. Compile and generate the ISO image (and the Linux container):&lt;br /&gt;
&lt;br /&gt;
* Go to the directory where you have downloaded the source of ''LBmake'' and compile it using the ''make'' tool:&lt;br /&gt;
 cd lbmake&lt;br /&gt;
 sudo make&lt;br /&gt;
&lt;br /&gt;
4. Once the image is generated you can test it virtualizing the system with QEMU.&amp;lt;ref&amp;gt;QEMU processor emulator: http://wiki.qemu.org/Main_Page&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Generate a disk image and use the ISO image as a live CD for the installation:&lt;br /&gt;
 qemu-img create -f qcow2 disk.qcow2 4G&lt;br /&gt;
 qemu-system-i386 -enable-kvm -cdrom devel/binary.hybrid.iso -hda disk.qcow2&lt;br /&gt;
&lt;br /&gt;
''NOTE: if you have a relatively recent machine, adding the option '-enable-kvm' you will take profit from the hardware virtualization, it will increase the speed and performance.''&lt;br /&gt;
&lt;br /&gt;
==== Linux container ====&lt;br /&gt;
&lt;br /&gt;
Optionally, from the ISO image you can create a Linux container with the following command:&lt;br /&gt;
 sudo make container&lt;br /&gt;
&lt;br /&gt;
''NOTE: before generating the container you have to create the ISO image first. If not, the previous command will generate firstly the ISO and after the container.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
As it is explained in the introduction, the Cloudy distribution is based in Debian GNU/Linux and made in a live ISO image.&lt;br /&gt;
&lt;br /&gt;
You can boot the system from the external device (CD/DVD/USB), or start the installation process by selecting the corresponding option from the menu.&lt;br /&gt;
&lt;br /&gt;
[[File:cloudy-boot-install.png|center]]&lt;br /&gt;
&lt;br /&gt;
The installation is the same as a standard Debian&amp;lt;ref&amp;gt;Debian installation procedure: http://www.debian.org/releases/stable/i386/&amp;lt;/ref&amp;gt;, and the steps can be sumarize in:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Services ===&lt;br /&gt;
&lt;br /&gt;
Below you can see what processes are currently available in Cloudy to be configured easily through the web interface.&lt;br /&gt;
&lt;br /&gt;
''&amp;quot;NOTE: each service is explained in the Cloudy website&amp;lt;ref&amp;gt;Cloudy contents: http://cloudy.community/features/&amp;lt;/ref&amp;gt;&amp;quot;''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Clommunity ====&lt;br /&gt;
* Getinconf (TincVPN client management)&lt;br /&gt;
* OpenVZ Web Panel (virtual machines management)&lt;br /&gt;
* Peer Streamer (distributed streaming)&lt;br /&gt;
* Syncthing (network file synchronization)&lt;br /&gt;
* Tahofe-LAFS (distributed file system)&lt;br /&gt;
* Webdav server&lt;br /&gt;
&lt;br /&gt;
==== Guifi ====&lt;br /&gt;
* Proxy3 (web proxy)&lt;br /&gt;
[[File:cloudy-guifi-proxy.png|center]]&lt;br /&gt;
&lt;br /&gt;
* SNPServices (monitoring/graphs)&lt;br /&gt;
[[File:cloudy-guifi-snpservices.png|center]]&lt;br /&gt;
&lt;br /&gt;
* DNSServices (DNS)&lt;br /&gt;
[[File:cloudy-guifi-dnsservices.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
&lt;br /&gt;
* http://cloudy.community&lt;br /&gt;
* http://wiki.clommunity-project.eu/soft:cloudservices&lt;br /&gt;
* http://clommunity-project.eu&lt;br /&gt;
* http://guifi.net&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_web_UI</id>
		<title>Cloudy web UI</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_web_UI"/>
				<updated>2015-05-12T19:12:08Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot; == Introduction ==  The Cloudy web User Interface (UI) uses an application called cDistro &amp;lt;ref name=&amp;quot;cdistro&amp;quot;&amp;gt;cDistro git repository: http://dev.cloudy.community/Guifi.net/we...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The Cloudy web User Interface (UI) uses an application called cDistro &amp;lt;ref name=&amp;quot;cdistro&amp;quot;&amp;gt;cDistro git repository: http://dev.cloudy.community/Guifi.net/web-interface&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
''(Add what it is)''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
The cDistro configuration is placed in /etc/cdistro.conf&lt;br /&gt;
&lt;br /&gt;
By default it has the following format:&lt;br /&gt;
&lt;br /&gt;
 #cdistro config&lt;br /&gt;
 SERVER=&amp;quot;/usr/bin/php&amp;quot;&lt;br /&gt;
 OPTS=&amp;quot;&amp;quot;&lt;br /&gt;
 BINDIP=&amp;quot;0.0.0.0&amp;quot;&lt;br /&gt;
 PORT=&amp;quot;7000&amp;quot;&lt;br /&gt;
 DOCROOT=&amp;quot;/var/local/cDistro&amp;quot;&lt;br /&gt;
 # SSHAUTH=1 &amp;lt;- check user with ssh2 connection http://www.php.net/manual/en/function.ssh2-auth-password.php (Require: libssh2-php)&lt;br /&gt;
 SSHAUTH=1&lt;br /&gt;
 # LOGIN=&amp;quot;root&amp;quot;&lt;br /&gt;
 ## PASSWORD = md5(md5('secret')) =&amp;gt; php -r 'echo md5(md5(&amp;quot;secret&amp;quot;)).&amp;quot;\n&amp;quot;;'&lt;br /&gt;
 #PASSWORD=&amp;quot;7022cd14c42ff272619d6beacdc9ffde&amp;quot;&lt;br /&gt;
 PORT_SSL=7443&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SERVER ===&lt;br /&gt;
&lt;br /&gt;
The path of the PHP executable.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/usr/bin/php&amp;quot; - in the case of Cloudy (Debian).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== OPTS ===&lt;br /&gt;
&lt;br /&gt;
PHP options.&lt;br /&gt;
&lt;br /&gt;
''(Add references or more info and an example)''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== BINDIP ===&lt;br /&gt;
&lt;br /&gt;
The IP address where the service will be listening.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;127.0.0.1&amp;quot; - will accept only petitions from localhost.&lt;br /&gt;
* &amp;quot;0.0.0.0&amp;quot; - will accept petitions from any address.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PORT ===&lt;br /&gt;
&lt;br /&gt;
The port opened by the service to listen to requests.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;7000&amp;quot; - opens the port 7000.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== DOCROOT ===&lt;br /&gt;
&lt;br /&gt;
The path of the cDistro application.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;/var/local/cDistro&amp;quot; - in the case of Cloudy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SSLAUTH ===&lt;br /&gt;
&lt;br /&gt;
Parameter that allows authentication via SSH2 in the application, i.e., to use the credentials that the SSH server of the system allows.&lt;br /&gt;
&lt;br /&gt;
Can be 0 or 1.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;1&amp;quot; - actives this option.&lt;br /&gt;
* &amp;quot;0&amp;quot; - disables this option (will require to define user and password).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== LOGIN ===&lt;br /&gt;
&lt;br /&gt;
The username to authenticate against the application.&lt;br /&gt;
&lt;br /&gt;
Should be a string without spaces.&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;cloudy&amp;quot; - this user can log-in with the password of PASSWORD.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PASSWORD ===&lt;br /&gt;
&lt;br /&gt;
The password of the user defined in LOGIN.&lt;br /&gt;
&lt;br /&gt;
Should be a hash over a hash MD5 (hexadecimal), i.e., a hash of the password hash: md5(md5(&amp;quot;PASSWORD&amp;quot;)).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;46d934e0f59ff1e2272f9f5f7950e5d9&amp;quot; - the hash of the string &amp;quot;PASSWORD&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''Examples of how to generate that hash in a terminal:'''&lt;br /&gt;
&lt;br /&gt;
 $ php -r 'echo md5(md5(&amp;quot;PASSWORD&amp;quot;)).&amp;quot;\n&amp;quot;;'&lt;br /&gt;
 46d934e0f59ff1e2272f9f5f7950e5d9&lt;br /&gt;
 $ printf &amp;quot;PASSWORD&amp;quot; | md5sum | awk '{printf $1}' | md5sum | awk '{print $1}'&lt;br /&gt;
 46d934e0f59ff1e2272f9f5f7950e5d9&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== PORT_SSL ===&lt;br /&gt;
&lt;br /&gt;
Port that Cloudy will use in the web interface with HTTPS (if SSL is enabled).&lt;br /&gt;
&lt;br /&gt;
'''Example:'''&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;7443&amp;quot; - access to the web interface in https://IP_SERVIDOR:7443.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy</id>
		<title>Cloudy</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy"/>
				<updated>2015-05-12T18:23:09Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Redirected page to Category:Cloudy&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Category:Cloudy]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_plug-ins</id>
		<title>Cloudy plug-ins</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_plug-ins"/>
				<updated>2015-05-12T18:22:53Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is a plug-in? ==&lt;br /&gt;
&lt;br /&gt;
Cloudy is a Debian-based Linux distribution that provides users a simple and convenient web interface to manage different services that are to be used in a Community Network (in our case, Guifi).&lt;br /&gt;
&lt;br /&gt;
At the same time, Cloudy offers a set of tools that allow a user to add a service to the system without need for advanced knowledges on networking or computers in general. These services are automatically published to the Community Network, so that anybody using Cloudy can use this new service.&lt;br /&gt;
&lt;br /&gt;
'''Plug-ins''' are the modular pieces of code that allow adding and removing these services. Therefore, we understand thata plug-in is a program or a piece of software that a user can add to the Cloudy distribution and that can be managed in a simple way from the web interface provided by Cloudy.&lt;br /&gt;
&lt;br /&gt;
== Adding services to Cloudy ==&lt;br /&gt;
&lt;br /&gt;
=== A brief introduction ===&lt;br /&gt;
&lt;br /&gt;
This guide will walk you through the process of adding a new service to Cloudy.&lt;br /&gt;
&lt;br /&gt;
In order to be clear and provide examples, we are going to be integrating a very simple service showing snippets of code along the way.&lt;br /&gt;
To follow the tutorial or to add complex services, will be nice any knowledge of Bash&amp;lt;ref name=&amp;quot;Bash&amp;quot;&amp;gt;(http://www.tldp.org/LDP/Bash-Beginners-Guide/Bash-Beginners-Guide.pdf)&amp;lt;/ref&amp;gt; and PHP&amp;lt;ref name=&amp;quot;PHP&amp;quot;&amp;gt;(https://php.net/manual/es/index.php)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the sake of simplicity, we will use Pastecat&amp;lt;ref name=&amp;quot;Pastecat&amp;quot;&amp;gt;(https://github.com/mvdan/pastecat)&amp;lt;/ref&amp;gt;. It is a good candidate because:&lt;br /&gt;
&lt;br /&gt;
* It's a standalone program&lt;br /&gt;
* It only needs to be installed in one node (no federation/syncrhonization)&lt;br /&gt;
* It's Built with Go, it's easy to distribute and deploy&lt;br /&gt;
* It doesn't need a configuration file nor any kind of setup&lt;br /&gt;
* It's very lightweight on resources&lt;br /&gt;
&lt;br /&gt;
=== Getting the binary ===&lt;br /&gt;
&lt;br /&gt;
The first thing we have to figure out is how to download and install the binary on Cloudy. Most software out there is already available as a package on Debian, but Pastecat isn't. If it were, it would be a matter of just running the command &amp;lt;code&amp;gt;apt-get install pastecat&amp;lt;/code&amp;gt; from PHP. Therefore we'll have to get it from someplace else.&lt;br /&gt;
&lt;br /&gt;
One option is to fetch the source and build it ourselves. This often means, however, that Cloudy should include a lot of build tools and libraries. In the case of Go, that would mean having its toolchain installed, which isn't very practical.&lt;br /&gt;
&lt;br /&gt;
A better option when the Debian package isn't available is to download the binary from upstream trusted sources via HTTPS and, preferably, checking digests or using signatures. We can use Github's releases page for that. Both options leave us with an executable file that we should be able to run directly on Cloudy.&lt;br /&gt;
&lt;br /&gt;
In this particular case we are going to download the binaries from the git repository with the following command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;wget https://github.com/mvdan/pastecat/releases/download/v0.3.0/pastecat_linux_386&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that in this case we are downloading a specific version for a Linux with a 386 architecture.&lt;br /&gt;
&lt;br /&gt;
Note that having the service as a Debian package has many advantages:&lt;br /&gt;
&lt;br /&gt;
* Updates are simple and need no extra work from Cloudy&lt;br /&gt;
* The package is compiled and built by Debian in a trusted way&lt;br /&gt;
* An init.d file is already provided&lt;br /&gt;
* Debian packages often contain small patches and fixes&lt;br /&gt;
&lt;br /&gt;
=== Testing it out ===&lt;br /&gt;
&lt;br /&gt;
Before adding Pastecat as a Cloudy service, we can configure and start it ourselves directly (i.e. manually), to see if it works and how. This way we can better understand what configuration options or command line parameters are we will need to run it as a service, and also to manage it once it is running.&lt;br /&gt;
&lt;br /&gt;
=== Adding the controller ===&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;web/plug/controllers&amp;lt;/code&amp;gt; we have one PHP file per service, which we call &amp;amp;quot;the controller&amp;amp;quot;. This is the code that will run when we enter the services page on the Cloudy web interface.&lt;br /&gt;
&lt;br /&gt;
==== Adding the index function ====&lt;br /&gt;
&lt;br /&gt;
We also want our service to be integrated in the Cloudy web structure. To do this, a few PHP scripts need to be created and added to our device. Altogether, and by the time being, we'll need to create a total of 2 scripts: &amp;lt;code&amp;gt;pastecat.PHP&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;pastecat.menu.PHP&amp;lt;/code&amp;gt;. The first one is the controller itself, this is, the script that renders the page and has all the information such as buttons or redirections. The other one is what allows our service to show up in the upper menu bar of Cloudy's web interface.&lt;br /&gt;
&lt;br /&gt;
The menu code will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;?PHP&lt;br /&gt;
//peerstreamer.menu.PHP&lt;br /&gt;
addMenu('Pastecat','pastecat','Clommunity');&amp;lt;/pre&amp;gt;&lt;br /&gt;
By now, we'll use a very simple PHP script in the controller:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;?PHP&lt;br /&gt;
//pastecat&lt;br /&gt;
$title=&amp;amp;quot;Pastecat&amp;amp;quot;;&lt;br /&gt;
&lt;br /&gt;
function index(){&lt;br /&gt;
    global $paspath,$title;&lt;br /&gt;
    global $staticFile;&lt;br /&gt;
&lt;br /&gt;
    $page=hlc(t($title));&lt;br /&gt;
    $page .= hl(t(&amp;amp;quot;Minimalist pastebin engine written in Go&amp;amp;quot;),4);&lt;br /&gt;
    $page .= par(t(&amp;amp;quot;A simple and self-hosted pastebin service written in Go&amp;amp;quot;).' '.t(&amp;amp;quot;Can use a variety of storage backends&amp;amp;quot;).' '.t(&amp;amp;quot; Designed to optionally remove pastes after a certain period of time.&amp;amp;quot;).' '.(&amp;amp;quot;If using a persistent storage backend, pastes will be kept between runs.&amp;amp;quot;).' '.t(&amp;amp;quot;This software runs the&amp;amp;quot;).' '.&amp;amp;quot;&amp;amp;lt;a href='http://paste.cat'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;paste.cat&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/a&amp;amp;gt;&amp;amp;quot;. t(&amp;amp;quot; public service.&amp;amp;quot;));&lt;br /&gt;
&lt;br /&gt;
    return(array('type' =&amp;amp;gt; 'render','page' =&amp;amp;gt; $page));&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
In our Cloudy system, these files must be placed at &amp;lt;code&amp;gt;/var/local/cDistro/plug/&amp;lt;/code&amp;gt; the first one at &amp;lt;code&amp;gt;menus&amp;lt;/code&amp;gt; directory and the second at &amp;lt;code&amp;gt;controllers&amp;lt;/code&amp;gt; directory. Once we've done this, we can go to our Cloudy system and access our new Pastecat.&lt;br /&gt;
&lt;br /&gt;
==== Making the controller install the service ====&lt;br /&gt;
&lt;br /&gt;
As said before, this step is made much more easier if the service is packaged in Debian. Since Pastecat isn't, we'll have to do it manually. This usually involves a combination of &amp;lt;code&amp;gt;wget&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;chmod&amp;lt;/code&amp;gt;. It is generally a good idea to keep the service's files under &amp;lt;code&amp;gt;/opt/SERVICENAME&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In our particular case, the first thing we need to do is downloading the binary from the release. In order to do this we will make use of the mentioned &amp;lt;code&amp;gt;wget&amp;lt;/code&amp;gt; command. Given a URL to a file, this command allows us to download this file in our system, and this is what we will do in our system (as mentioned before):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;wget https://github.com/mvdan/pastecat/releases/download/v0.3.0/pastecat_linux_386&amp;lt;/pre&amp;gt;&lt;br /&gt;
Once we have the binary, we just need to move it to a directory where executable files use to be located. In our case, we will use the directory /opt/pastecat/. To move these files through our system we will use the command &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt;. However, first of all we need to create the directory where we will place our binary. To do this we use the &amp;lt;code&amp;gt;mkdir&amp;lt;/code&amp;gt; command as is shown below:&lt;br /&gt;
&lt;br /&gt;
mkdir -p /opt/pastecat/&lt;br /&gt;
&lt;br /&gt;
Once we have our directory created, it is time to move the binary there:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;mv current_directory/pastecat_linux_386 /opt/pastecat/&amp;lt;/pre&amp;gt;&lt;br /&gt;
where current_directory is the directory where we previously downloaded the binary. Since the binary name depends on the architecture, in order to simplfy the controller's code, we will change its name to something more simple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;mv /opt/pastecat/pastecat_linux_386 /opt/pastecat/pastecat&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now our binary is called &amp;lt;code&amp;gt;pastecat&amp;lt;/code&amp;gt; insted of &amp;lt;code&amp;gt;pastecat_linux_386&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These steps are the minimum requiered to install a service which is not provided in the Debian official repositories. However, to an end user, it would look like a nightmare to run these commands in a console connected through ssh to its device, so what we are going to do now, is create a bash script which will be called later from the web interface by clicking a button.&lt;br /&gt;
&lt;br /&gt;
This script is the first version of the pastecat controller. For the time being, We will just include a function to install pastecat in a device. Later we will include some other functions to add more facilities to our service.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/bash&lt;br /&gt;
PCPATH=&amp;amp;quot;/opt/pastecat/&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
doInstall() {&lt;br /&gt;
    if isInstall&lt;br /&gt;
    then&lt;br /&gt;
        echo &amp;amp;quot;Pastecat is already installed.&amp;amp;quot;&lt;br /&gt;
        return&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    # Creating directory and switching&lt;br /&gt;
    mkdir -p $pcpath &amp;amp;amp;&amp;amp;amp; cd $pcpath&lt;br /&gt;
&lt;br /&gt;
    # Getting file&lt;br /&gt;
    wget https://github.com/mvdan/pastecat/releases/download/v0.3.0/pastecat_linux_386&lt;br /&gt;
&lt;br /&gt;
    # Changing name so controller can invoke it generically&lt;br /&gt;
    mv pastecat_linux_386 pastecat&lt;br /&gt;
    chmod +x pastecat&lt;br /&gt;
    &lt;br /&gt;
    cd -&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
isInstalled() {&lt;br /&gt;
    [ -d $pcpath ] &amp;amp;amp;&amp;amp;amp; return 0&lt;br /&gt;
    return 1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
case $1 in&lt;br /&gt;
    &amp;amp;quot;install&amp;amp;quot;)&lt;br /&gt;
        shift&lt;br /&gt;
        doInstall $@&lt;br /&gt;
        ;;&lt;br /&gt;
esac&amp;lt;/pre&amp;gt;&lt;br /&gt;
We can see how the lasts steps are done within the same function, allowing us to install the software in the device.&lt;br /&gt;
&lt;br /&gt;
==== Making the controller use Pastecat ====&lt;br /&gt;
&lt;br /&gt;
===== Start the service =====&lt;br /&gt;
&lt;br /&gt;
The next thing we want is our software to be used through the web interface. In order to do this, we will include a new option to the main page of pastecat, and also integrate a new function to the controller script to manage the binary. We will add the button like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$page .= addButton(array('label'=&amp;amp;gt;t('Create a Pastecat server'),'href'=&amp;amp;gt;$staticFile.'/pastecat/publish'));&amp;lt;/pre&amp;gt;&lt;br /&gt;
after the &amp;lt;code&amp;gt;Pastecat is installed&amp;lt;/code&amp;gt; message. The next thing will be implementing the function &amp;lt;code&amp;gt;publish&amp;lt;/code&amp;gt; in the same PHP. This function is the responsible of calling the appropiate function in the controller and to announce our server usign the avahi technology. The difference with this function is that it requieres a form to introduce data, so in the end we will have a total of 2 functions: a get and a post:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function publish_get() {&lt;br /&gt;
    global $pcpath,$title;&lt;br /&gt;
    global $staticFile;&lt;br /&gt;
&lt;br /&gt;
    $page = hlc(t($title));&lt;br /&gt;
    $page .= hlc(t('Publish a pastecat server'),2);&lt;br /&gt;
    $page .= par(t(&amp;amp;quot;Write the port to publish your Pastecat service&amp;amp;quot;));&lt;br /&gt;
    $page .= createForm(array('class'=&amp;amp;gt;'form-horizontal'));&lt;br /&gt;
    $page .= addInput('description',t('Describe this server'));&lt;br /&gt;
    $page .= addSubmit(array('label'=&amp;amp;gt;t('Publish'),'class'=&amp;amp;gt;'btn btn-primary'));&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Cancel'),'href'=&amp;amp;gt;$staticFile.'/peerstreamer'));&lt;br /&gt;
&lt;br /&gt;
    return(array('type' =&amp;amp;gt; 'render','page' =&amp;amp;gt; $page));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function publish_post() {&lt;br /&gt;
    $port = $_POST['port'];&lt;br /&gt;
    $description = $_POST['description'];&lt;br /&gt;
    $ip = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;lt;pre&amp;amp;gt;&amp;amp;quot;;&lt;br /&gt;
    $page .= _pcsource($description);&lt;br /&gt;
    $page .= &amp;amp;quot;&amp;amp;lt;/pre&amp;amp;gt;&amp;amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    return(array('type' =&amp;amp;gt; 'render','page' =&amp;amp;gt; $page));&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
As we can see, in the &amp;lt;code&amp;gt;post&amp;lt;/code&amp;gt; function we are invoking another function. The reason to do this is to write a more simple and modular code. In this function, we are finally calling the script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function _pcsource($port,$description) {&lt;br /&gt;
    global $pcpath,$pcprogram,$title,$pcutils,$avahi_type,$port;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
    $device = getCommunityDev()['output'][0];&lt;br /&gt;
    $ipserver = getCommunityIP()['output'][0];&lt;br /&gt;
&lt;br /&gt;
    if ($description == &amp;amp;quot;&amp;amp;quot;) $description = $type;&lt;br /&gt;
&lt;br /&gt;
    $cmd = $pcutils.&amp;amp;quot; publish '$port' '$description';&lt;br /&gt;
    execute_program_detached($cmd);&lt;br /&gt;
&lt;br /&gt;
    $page .= t($ipserver);&lt;br /&gt;
    $page .= par(t('Published this server.'));&lt;br /&gt;
&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Back'),'href'=&amp;amp;gt;$staticFile.'/pastecat'));&lt;br /&gt;
&lt;br /&gt;
    return($page)&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
The next thing to do will be create the function &amp;lt;code&amp;gt;publish&amp;lt;/code&amp;gt; in the controller, so we will add a new function to the basic controller we had back at section '''3.2'''. We will add a new flag called publish, so the first executed part of the script will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if [ $# -lt 1 ]&lt;br /&gt;
then&lt;br /&gt;
    doHelp&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
case $1 in&lt;br /&gt;
    &amp;amp;quot;install&amp;amp;quot;)&lt;br /&gt;
        shift&lt;br /&gt;
        doInstall $@&lt;br /&gt;
        ;;&lt;br /&gt;
    &amp;amp;quot;publish&amp;amp;quot;)&lt;br /&gt;
        shift&lt;br /&gt;
        doServer $@&lt;br /&gt;
        ;;&lt;br /&gt;
esac&amp;lt;/pre&amp;gt;&lt;br /&gt;
As we can see, when the script's first argument is &amp;lt;code&amp;gt;publish&amp;lt;/code&amp;gt;, we shift the rest of arguments and call the function &amp;lt;code&amp;gt;doServer&amp;lt;/code&amp;gt;. In this function, we must start the service with the requiered arguments, so the first thing we'll do is put the arguments into local variables. Once we do that the common thing would be to launche the Pastecat server, but since it might be called with root permissions (and this is bad) we must run it as a &amp;lt;code&amp;gt;nobody&amp;lt;/code&amp;gt; user. The issue is that the &amp;lt;code&amp;gt;nobody&amp;lt;/code&amp;gt; user has merely no permissions... and pastecat need some permissions to create folders and text files. In order to allow the &amp;lt;code&amp;gt;nobody&amp;lt;/code&amp;gt; user to do that, first of all we will create a folder and grant permissions to almost everyone to it. We will use &amp;lt;code&amp;gt;chmod&amp;lt;/code&amp;gt; again. Now, the user can create files and directories within this directory, so we can now run pastecat. Finally, we keep the pid in a variable in case we want to use it in later updates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;doServer() {&lt;br /&gt;
    # Turning machine into a server&lt;br /&gt;
&lt;br /&gt;
    local port=${1:-&amp;amp;quot;&amp;amp;quot;}&lt;br /&gt;
    local description=${2:-&amp;amp;quot;&amp;amp;quot;}&lt;br /&gt;
    local ip=${3:-&amp;amp;quot;0.0.0.0&amp;amp;quot;}&lt;br /&gt;
&lt;br /&gt;
    # Creating directory with nobody permissions&lt;br /&gt;
    mkdir -p &amp;amp;quot;/var/local/pastecat&amp;amp;quot;&lt;br /&gt;
    chmod 777 &amp;amp;quot;/var/local/pastecat&amp;amp;quot; &amp;amp;amp;&amp;amp;amp; cd &amp;amp;quot;/var/local/pastecat&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # Running pastecat &lt;br /&gt;
    cmd='su '$PCUSER' -c &amp;amp;quot;{ '$PCPATH$PCPROG' -l :'$port' &amp;amp;gt; '$LOGFILE' 2&amp;amp;gt;&amp;amp;amp;1 &amp;amp;amp; }; echo \$!&amp;amp;quot;'&lt;br /&gt;
    pidpc=$(eval $cmd)          # keeping PID for future needs...&lt;br /&gt;
&lt;br /&gt;
    cd -&lt;br /&gt;
&lt;br /&gt;
    # Using the PID, we could carry on process control so if the pastecat process die, we can also&lt;br /&gt;
    # stop the avahi process to avoid &amp;amp;quot;false connections&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that we are using some global variables that were not defined before such as &amp;lt;code&amp;gt;PCUSER&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LOGFILE&amp;lt;/code&amp;gt;. By default, we set these variables like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;PCPATH=&amp;amp;quot;/opt/pastecat/&amp;amp;quot;&lt;br /&gt;
PCPROG=&amp;amp;quot;pastecat&amp;amp;quot;&lt;br /&gt;
LOGFILE=&amp;amp;quot;/dev/null&amp;amp;quot;&lt;br /&gt;
PCUSER=&amp;amp;quot;nobody&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Stop the service =====&lt;br /&gt;
&lt;br /&gt;
Sometimes, we may also want to stop out service, so we will provide a button to do so. The first thing would be creating the button, but if we think a little, we will figure out that before doing this, we need a way to know if our service is running. In addition, we also need a way to stop our service. Since we are running on Linux, we can easily achieve that by using the &amp;lt;code&amp;gt;kill&amp;lt;/code&amp;gt; command. The thing is that to use this command, we need the Process ID (PID). Luckily for us, we already kept this number when we created the pastecat server with &amp;lt;code&amp;gt;pidpc=$(eval $cmd)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now that we have everything we need to kill our process, let's provide a way so the PHP can detect whether Pastecat is running or not. An easy and resulting way to do this is storing some useful data in a file and delete this file when pastecat is stopped. This way, we make sure that this file will only exists when Pastecat is running. This file will be created from the controller adding the following lines right below the sentence we mentioned in the previous paragraph:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Writting server info to file&lt;br /&gt;
info=&amp;amp;quot;$pidpc http://$ip:$port&amp;amp;quot;          # Separator is space character&lt;br /&gt;
echo $info &amp;amp;gt; $PCFILE&amp;lt;/pre&amp;gt;&lt;br /&gt;
where &amp;lt;code&amp;gt;$PCFILE&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;/var/run/pc.info&amp;lt;/code&amp;gt;. Note that the content of this file will be the PID and the complete direction of our Pastecat server.&lt;br /&gt;
&lt;br /&gt;
Now we have a way to know if our server is up or down, so we can add the &amp;amp;quot;stop&amp;amp;quot; button in the web interfae. We will modify a little bit the PHP script that we had before, just by addind anther advertisement indicating whether Pastecat is up or down, and 2 more buttons if it is running. So, in our index function, within the condition that checks if Pastecat is installed we will have the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$page .= &amp;amp;quot;&amp;amp;lt;div class='alert alert-success text-center'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;Pastecat is installed&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/div&amp;amp;gt;\n&amp;amp;quot;;&lt;br /&gt;
if ( isRunning() ) {&lt;br /&gt;
    $page .= &amp;amp;quot;&amp;amp;lt;div class='alert alert-success text-center'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;Pastecat is running&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/div&amp;amp;gt;\n&amp;amp;quot;;&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Go to server'),'href'=&amp;amp;gt;'http://'. getCommunityIP()['output'][0] .':'. $port));&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Stop server'),'href'=&amp;amp;gt;$staticFile.'/pastecat/stop'));&lt;br /&gt;
} else  {&lt;br /&gt;
    $page .= &amp;amp;quot;&amp;amp;lt;div class='alert alert-error text-center'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;Pastecat is not running&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/div&amp;amp;gt;\n&amp;amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
$page .= addButton(array('label'=&amp;amp;gt;t('Create a Pastecat server'),'href'=&amp;amp;gt;$staticFile.'/pastecat/publish'));&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this piece of code, we can appreciate 2 new features in our code. The first one is a check function called &amp;lt;code&amp;gt;isRunning()&amp;lt;/code&amp;gt;. This function looks very similar to the function we used to check if Pastecat is installed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function isRunning() {&lt;br /&gt;
    // Returns whether pastecat is running or not&lt;br /&gt;
    global $pcfile;&lt;br /&gt;
&lt;br /&gt;
    return(file_exists($pcfile));   &lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
It is a simple as it seems, it just checks if the file we created when starting the server still exists. The second thing we can notice in the new PHP code is the existance of a new function called &amp;lt;code&amp;gt;stop&amp;lt;/code&amp;gt;. This function will invoke another function in the controller which will stop the pastecat:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function stop() {&lt;br /&gt;
    // Stops Pastecat server&lt;br /&gt;
    global $pcpath,$pcprogram,$title,$pcutils,$avahi_type,$port;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
    $cmd = $pcutils.&amp;amp;quot; stop &amp;amp;quot;;&lt;br /&gt;
    execute_program_detached($cmd);&lt;br /&gt;
&lt;br /&gt;
    return(array('type'=&amp;amp;gt;'redirect','url'=&amp;amp;gt;$staticFile.'/pastecat'));&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to make the controller understand this order, we will modify the case and add the new function. In the &amp;lt;code&amp;gt;case&amp;lt;/code&amp;gt; statement, we will add the following under the &amp;lt;code&amp;gt;install&amp;lt;/code&amp;gt; option:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;quot;stop&amp;amp;quot;)&lt;br /&gt;
    shift&lt;br /&gt;
    doStop $@&lt;br /&gt;
    ;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
This calls the function &amp;lt;code&amp;gt;doStop&amp;lt;/code&amp;gt; within the controller. This function will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;doStop() {&lt;br /&gt;
    # Stopping pastecat server&lt;br /&gt;
    pcpid=$(cat $PCFILE | cut -d' ' -f1)&lt;br /&gt;
    kill $pcpid&lt;br /&gt;
&lt;br /&gt;
    # Removing info file&lt;br /&gt;
    rm $PCFILE&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
This function just gets the pastecat's PID from the file we created before, kills the process and finally removes the file so the PHP scripts can know that pastecat is now down.&lt;br /&gt;
&lt;br /&gt;
Now we can create a pastecat instance server and stop it. However, there is still something missing: make the other users see our service. And this is why we are using avahi.&lt;br /&gt;
&lt;br /&gt;
=== Avahi service publishing ===&lt;br /&gt;
&lt;br /&gt;
On of the best things in Cloudy is the facility of publishing our service as a publication in the avahi network, allowing other users to know what we are offering and joining our service. To do this, we first need to add a few lines to the PHP controller, just after we've called the controller to start the pastecat instance. We will add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$description = str_replace(' ', '', $description);&lt;br /&gt;
$temp = avahi_publish($avahi_type, $description, $port, &amp;amp;quot;&amp;amp;quot;);&lt;br /&gt;
$page .= ptxt($temp);&amp;lt;/pre&amp;gt;&lt;br /&gt;
So in the end our function will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function _pcsource($port,$description) {&lt;br /&gt;
    global $pcpath,$pcprogram,$title,$pcutils,$avahi_type;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
    $device = getCommunityDev()['output'][0];&lt;br /&gt;
    $ipserver = getCommunityIP()['output'][0];&lt;br /&gt;
&lt;br /&gt;
    if ($description == &amp;amp;quot;&amp;amp;quot;) $description = $type;&lt;br /&gt;
&lt;br /&gt;
    $cmd = $pcutils.&amp;amp;quot; publish '$port' '$description'&amp;amp;quot;;&lt;br /&gt;
    execute_program_detached($cmd);&lt;br /&gt;
&lt;br /&gt;
    $page .= t($ipserver);&lt;br /&gt;
    $page .= par(t('Published this server.'));&lt;br /&gt;
    $description = str_replace(' ', '', $description);&lt;br /&gt;
    $temp = avahi_publish($avahi_type, $description, $port, &amp;amp;quot;&amp;amp;quot;);&lt;br /&gt;
    $page .= ptxt($temp);&lt;br /&gt;
&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Back'),'href'=&amp;amp;gt;$staticFile.'/pastecat'));&lt;br /&gt;
&lt;br /&gt;
    return($page)&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
With this simple step, we announced our service in the avahi network. However the work does not end here, there is still one more thing to do: create a button and program it so when clicked, it directly goes to our pastecat server.&lt;br /&gt;
&lt;br /&gt;
To do this there is a folder called &amp;lt;code&amp;gt;avahi&amp;lt;/code&amp;gt; within the &amp;lt;code&amp;gt;plug&amp;lt;/code&amp;gt; directory. The scripts that define the function carried on when the button is clicked are defined in different files within this directory, therefor we will create a new file called &amp;lt;code&amp;gt;pastecat.avahi.PHP&amp;lt;/code&amp;gt; which will contain this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;?PHP&lt;br /&gt;
// plug/avahi/pastecat.avahi.PHP&lt;br /&gt;
&lt;br /&gt;
addAvahi('pastecat','fpcserver');&lt;br /&gt;
&lt;br /&gt;
function fpcserver($dates){&lt;br /&gt;
    global $staticFile;&lt;br /&gt;
&lt;br /&gt;
    return (&amp;amp;quot;&amp;amp;lt;a class='btn' href='http://&amp;amp;quot; .$dates['ip'] .&amp;amp;quot;:&amp;amp;quot;. $dates['port'].&amp;amp;quot;'&amp;amp;gt;Go to server&amp;amp;lt;/a&amp;amp;gt;  &amp;amp;quot;);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will create a button besides the avahi announcement line that will point to our server.&lt;br /&gt;
&lt;br /&gt;
Now that we have our service announced, we want it to dissappear when we stop the pastecat service. This last step is very simple yet important. It consist of a few lines in the PHP function called stop. Until now, this function just called the controller and stopped the pastecat, but now it will also stop the avahi publication and show a flash comment so the user knwo it worked:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$temp = avahi_unpublish($avahi_type, $port);&lt;br /&gt;
$flash = ptxt($temp);&lt;br /&gt;
setFlash($flash);&amp;lt;/pre&amp;gt;&lt;br /&gt;
These lines will be added just after the &amp;lt;code&amp;gt;execute_program_detached($cmd)&amp;lt;/code&amp;gt; sentence in the stop function.&lt;br /&gt;
&lt;br /&gt;
=== Final ===&lt;br /&gt;
&lt;br /&gt;
Finally just comment that all the files implemented in this tutorial can be found in a Github repository, linked in the External Link section, also with this tutorial in Markdown format (md).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
&lt;br /&gt;
https://github.com/Clommunity/Doc/tree/master/plugins/pastecat&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Cloudy]]&lt;br /&gt;
[[ca:Cloudy_plug-ins]]&lt;br /&gt;
[[es:Cloudy_plug-ins]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Category:Cloudy</id>
		<title>Category:Cloudy</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Category:Cloudy"/>
				<updated>2015-05-12T18:22:17Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: Created page with &amp;quot;More information: * http://cloudy.community * http://wiki.clommunity-project.eu/soft:cloudservices&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;More information:&lt;br /&gt;
* http://cloudy.community&lt;br /&gt;
* http://wiki.clommunity-project.eu/soft:cloudservices&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	<entry>
		<id>http://en.wiki.guifi.net/wiki/Cloudy_plug-ins</id>
		<title>Cloudy plug-ins</title>
		<link rel="alternate" type="text/html" href="http://en.wiki.guifi.net/wiki/Cloudy_plug-ins"/>
				<updated>2015-04-22T15:47:46Z</updated>
		
		<summary type="html">&lt;p&gt;Conxuro: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is a plug-in? ==&lt;br /&gt;
&lt;br /&gt;
Cloudy is a Debian-based Linux distribution that provides users a simple and convenient web interface to manage different services that are to be used in a Community Network (in our case, Guifi).&lt;br /&gt;
&lt;br /&gt;
At the same time, Cloudy offers a set of tools that allow a user to add a service to the system without need for advanced knowledges on networking or computers in general. These services are automatically published to the Community Network, so that anybody using Cloudy can use this new service.&lt;br /&gt;
&lt;br /&gt;
'''Plug-ins''' are the modular pieces of code that allow adding and removing these services. Therefore, we understand thata plug-in is a program or a piece of software that a user can add to the Cloudy distribution and that can be managed in a simple way from the web interface provided by Cloudy.&lt;br /&gt;
&lt;br /&gt;
== Adding services to Cloudy ==&lt;br /&gt;
&lt;br /&gt;
=== A brief introduction ===&lt;br /&gt;
&lt;br /&gt;
This guide will walk you through the process of adding a new service to Cloudy.&lt;br /&gt;
&lt;br /&gt;
In order to be clear and provide examples, we are going to be integrating a very simple service showing snippets of code along the way.&lt;br /&gt;
To follow the tutorial or to add complex services, will be nice any knowledge of Bash&amp;lt;ref name=&amp;quot;Bash&amp;quot;&amp;gt;(http://www.tldp.org/LDP/Bash-Beginners-Guide/Bash-Beginners-Guide.pdf)&amp;lt;/ref&amp;gt; and PHP&amp;lt;ref name=&amp;quot;PHP&amp;quot;&amp;gt;(https://php.net/manual/es/index.php)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For the sake of simplicity, we will use Pastecat&amp;lt;ref name=&amp;quot;Pastecat&amp;quot;&amp;gt;(https://github.com/mvdan/pastecat)&amp;lt;/ref&amp;gt;. It is a good candidate because:&lt;br /&gt;
&lt;br /&gt;
* It's a standalone program&lt;br /&gt;
* It only needs to be installed in one node (no federation/syncrhonization)&lt;br /&gt;
* It's Built with Go, it's easy to distribute and deploy&lt;br /&gt;
* It doesn't need a configuration file nor any kind of setup&lt;br /&gt;
* It's very lightweight on resources&lt;br /&gt;
&lt;br /&gt;
=== Getting the binary ===&lt;br /&gt;
&lt;br /&gt;
The first thing we have to figure out is how to download and install the binary on Cloudy. Most software out there is already available as a package on Debian, but Pastecat isn't. If it were, it would be a matter of just running the command &amp;lt;code&amp;gt;apt-get install pastecat&amp;lt;/code&amp;gt; from PHP. Therefore we'll have to get it from someplace else.&lt;br /&gt;
&lt;br /&gt;
One option is to fetch the source and build it ourselves. This often means, however, that Cloudy should include a lot of build tools and libraries. In the case of Go, that would mean having its toolchain installed, which isn't very practical.&lt;br /&gt;
&lt;br /&gt;
A better option when the Debian package isn't available is to download the binary from upstream trusted sources via HTTPS and, preferably, checking digests or using signatures. We can use Github's releases page for that. Both options leave us with an executable file that we should be able to run directly on Cloudy.&lt;br /&gt;
&lt;br /&gt;
In this particular case we are going to download the binaries from the git repository with the following command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;wget https://github.com/mvdan/pastecat/releases/download/v0.3.0/pastecat_linux_386&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that in this case we are downloading a specific version for a Linux with a 386 architecture.&lt;br /&gt;
&lt;br /&gt;
Note that having the service as a Debian package has many advantages:&lt;br /&gt;
&lt;br /&gt;
* Updates are simple and need no extra work from Cloudy&lt;br /&gt;
* The package is compiled and built by Debian in a trusted way&lt;br /&gt;
* An init.d file is already provided&lt;br /&gt;
* Debian packages often contain small patches and fixes&lt;br /&gt;
&lt;br /&gt;
=== Testing it out ===&lt;br /&gt;
&lt;br /&gt;
Before adding Pastecat as a Cloudy service, we can configure and start it ourselves directly (i.e. manually), to see if it works and how. This way we can better understand what configuration options or command line parameters are we will need to run it as a service, and also to manage it once it is running.&lt;br /&gt;
&lt;br /&gt;
=== Adding the controller ===&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;web/plug/controllers&amp;lt;/code&amp;gt; we have one PHP file per service, which we call &amp;amp;quot;the controller&amp;amp;quot;. This is the code that will run when we enter the services page on the Cloudy web interface.&lt;br /&gt;
&lt;br /&gt;
==== Adding the index function ====&lt;br /&gt;
&lt;br /&gt;
We also want our service to be integrated in the Cloudy web structure. To do this, a few PHP scripts need to be created and added to our device. Altogether, and by the time being, we'll need to create a total of 2 scripts: &amp;lt;code&amp;gt;pastecat.PHP&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;pastecat.menu.PHP&amp;lt;/code&amp;gt;. The first one is the controller itself, this is, the script that renders the page and has all the information such as buttons or redirections. The other one is what allows our service to show up in the upper menu bar of Cloudy's web interface.&lt;br /&gt;
&lt;br /&gt;
The menu code will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;?PHP&lt;br /&gt;
//peerstreamer.menu.PHP&lt;br /&gt;
addMenu('Pastecat','pastecat','Clommunity');&amp;lt;/pre&amp;gt;&lt;br /&gt;
By now, we'll use a very simple PHP script in the controller:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;?PHP&lt;br /&gt;
//pastecat&lt;br /&gt;
$title=&amp;amp;quot;Pastecat&amp;amp;quot;;&lt;br /&gt;
&lt;br /&gt;
function index(){&lt;br /&gt;
    global $paspath,$title;&lt;br /&gt;
    global $staticFile;&lt;br /&gt;
&lt;br /&gt;
    $page=hlc(t($title));&lt;br /&gt;
    $page .= hl(t(&amp;amp;quot;Minimalist pastebin engine written in Go&amp;amp;quot;),4);&lt;br /&gt;
    $page .= par(t(&amp;amp;quot;A simple and self-hosted pastebin service written in Go&amp;amp;quot;).' '.t(&amp;amp;quot;Can use a variety of storage backends&amp;amp;quot;).' '.t(&amp;amp;quot; Designed to optionally remove pastes after a certain period of time.&amp;amp;quot;).' '.(&amp;amp;quot;If using a persistent storage backend, pastes will be kept between runs.&amp;amp;quot;).' '.t(&amp;amp;quot;This software runs the&amp;amp;quot;).' '.&amp;amp;quot;&amp;amp;lt;a href='http://paste.cat'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;paste.cat&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/a&amp;amp;gt;&amp;amp;quot;. t(&amp;amp;quot; public service.&amp;amp;quot;));&lt;br /&gt;
&lt;br /&gt;
    return(array('type' =&amp;amp;gt; 'render','page' =&amp;amp;gt; $page));&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
In our Cloudy system, these files must be placed at &amp;lt;code&amp;gt;/var/local/cDistro/plug/&amp;lt;/code&amp;gt; the first one at &amp;lt;code&amp;gt;menus&amp;lt;/code&amp;gt; directory and the second at &amp;lt;code&amp;gt;controllers&amp;lt;/code&amp;gt; directory. Once we've done this, we can go to our Cloudy system and access our new Pastecat.&lt;br /&gt;
&lt;br /&gt;
==== Making the controller install the service ====&lt;br /&gt;
&lt;br /&gt;
As said before, this step is made much more easier if the service is packaged in Debian. Since Pastecat isn't, we'll have to do it manually. This usually involves a combination of &amp;lt;code&amp;gt;wget&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;chmod&amp;lt;/code&amp;gt;. It is generally a good idea to keep the service's files under &amp;lt;code&amp;gt;/opt/SERVICENAME&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In our particular case, the first thing we need to do is downloading the binary from the release. In order to do this we will make use of the mentioned &amp;lt;code&amp;gt;wget&amp;lt;/code&amp;gt; command. Given a URL to a file, this command allows us to download this file in our system, and this is what we will do in our system (as mentioned before):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;wget https://github.com/mvdan/pastecat/releases/download/v0.3.0/pastecat_linux_386&amp;lt;/pre&amp;gt;&lt;br /&gt;
Once we have the binary, we just need to move it to a directory where executable files use to be located. In our case, we will use the directory /opt/pastecat/. To move these files through our system we will use the command &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt;. However, first of all we need to create the directory where we will place our binary. To do this we use the &amp;lt;code&amp;gt;mkdir&amp;lt;/code&amp;gt; command as is shown below:&lt;br /&gt;
&lt;br /&gt;
mkdir -p /opt/pastecat/&lt;br /&gt;
&lt;br /&gt;
Once we have our directory created, it is time to move the binary there:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;mv current_directory/pastecat_linux_386 /opt/pastecat/&amp;lt;/pre&amp;gt;&lt;br /&gt;
where current_directory is the directory where we previously downloaded the binary. Since the binary name depends on the architecture, in order to simplfy the controller's code, we will change its name to something more simple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;mv /opt/pastecat/pastecat_linux_386 /opt/pastecat/pastecat&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now our binary is called &amp;lt;code&amp;gt;pastecat&amp;lt;/code&amp;gt; insted of &amp;lt;code&amp;gt;pastecat_linux_386&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These steps are the minimum requiered to install a service which is not provided in the Debian official repositories. However, to an end user, it would look like a nightmare to run these commands in a console connected through ssh to its device, so what we are going to do now, is create a bash script which will be called later from the web interface by clicking a button.&lt;br /&gt;
&lt;br /&gt;
This script is the first version of the pastecat controller. For the time being, We will just include a function to install pastecat in a device. Later we will include some other functions to add more facilities to our service.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#!/bin/bash&lt;br /&gt;
PCPATH=&amp;amp;quot;/opt/pastecat/&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
doInstall() {&lt;br /&gt;
    if isInstall&lt;br /&gt;
    then&lt;br /&gt;
        echo &amp;amp;quot;Pastecat is already installed.&amp;amp;quot;&lt;br /&gt;
        return&lt;br /&gt;
    fi&lt;br /&gt;
&lt;br /&gt;
    # Creating directory and switching&lt;br /&gt;
    mkdir -p $pcpath &amp;amp;amp;&amp;amp;amp; cd $pcpath&lt;br /&gt;
&lt;br /&gt;
    # Getting file&lt;br /&gt;
    wget https://github.com/mvdan/pastecat/releases/download/v0.3.0/pastecat_linux_386&lt;br /&gt;
&lt;br /&gt;
    # Changing name so controller can invoke it generically&lt;br /&gt;
    mv pastecat_linux_386 pastecat&lt;br /&gt;
    chmod +x pastecat&lt;br /&gt;
    &lt;br /&gt;
    cd -&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
isInstalled() {&lt;br /&gt;
    [ -d $pcpath ] &amp;amp;amp;&amp;amp;amp; return 0&lt;br /&gt;
    return 1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
case $1 in&lt;br /&gt;
    &amp;amp;quot;install&amp;amp;quot;)&lt;br /&gt;
        shift&lt;br /&gt;
        doInstall $@&lt;br /&gt;
        ;;&lt;br /&gt;
esac&amp;lt;/pre&amp;gt;&lt;br /&gt;
We can see how the lasts steps are done within the same function, allowing us to install the software in the device.&lt;br /&gt;
&lt;br /&gt;
==== Making the controller use Pastecat ====&lt;br /&gt;
&lt;br /&gt;
===== Start the service =====&lt;br /&gt;
&lt;br /&gt;
The next thing we want is our software to be used through the web interface. In order to do this, we will include a new option to the main page of pastecat, and also integrate a new function to the controller script to manage the binary. We will add the button like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$page .= addButton(array('label'=&amp;amp;gt;t('Create a Pastecat server'),'href'=&amp;amp;gt;$staticFile.'/pastecat/publish'));&amp;lt;/pre&amp;gt;&lt;br /&gt;
after the &amp;lt;code&amp;gt;Pastecat is installed&amp;lt;/code&amp;gt; message. The next thing will be implementing the function &amp;lt;code&amp;gt;publish&amp;lt;/code&amp;gt; in the same PHP. This function is the responsible of calling the appropiate function in the controller and to announce our server usign the avahi technology. The difference with this function is that it requieres a form to introduce data, so in the end we will have a total of 2 functions: a get and a post:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function publish_get() {&lt;br /&gt;
    global $pcpath,$title;&lt;br /&gt;
    global $staticFile;&lt;br /&gt;
&lt;br /&gt;
    $page = hlc(t($title));&lt;br /&gt;
    $page .= hlc(t('Publish a pastecat server'),2);&lt;br /&gt;
    $page .= par(t(&amp;amp;quot;Write the port to publish your Pastecat service&amp;amp;quot;));&lt;br /&gt;
    $page .= createForm(array('class'=&amp;amp;gt;'form-horizontal'));&lt;br /&gt;
    $page .= addInput('description',t('Describe this server'));&lt;br /&gt;
    $page .= addSubmit(array('label'=&amp;amp;gt;t('Publish'),'class'=&amp;amp;gt;'btn btn-primary'));&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Cancel'),'href'=&amp;amp;gt;$staticFile.'/peerstreamer'));&lt;br /&gt;
&lt;br /&gt;
    return(array('type' =&amp;amp;gt; 'render','page' =&amp;amp;gt; $page));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function publish_post() {&lt;br /&gt;
    $port = $_POST['port'];&lt;br /&gt;
    $description = $_POST['description'];&lt;br /&gt;
    $ip = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;lt;pre&amp;amp;gt;&amp;amp;quot;;&lt;br /&gt;
    $page .= _pcsource($description);&lt;br /&gt;
    $page .= &amp;amp;quot;&amp;amp;lt;/pre&amp;amp;gt;&amp;amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    return(array('type' =&amp;amp;gt; 'render','page' =&amp;amp;gt; $page));&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
As we can see, in the &amp;lt;code&amp;gt;post&amp;lt;/code&amp;gt; function we are invoking another function. The reason to do this is to write a more simple and modular code. In this function, we are finally calling the script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function _pcsource($port,$description) {&lt;br /&gt;
    global $pcpath,$pcprogram,$title,$pcutils,$avahi_type,$port;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
    $device = getCommunityDev()['output'][0];&lt;br /&gt;
    $ipserver = getCommunityIP()['output'][0];&lt;br /&gt;
&lt;br /&gt;
    if ($description == &amp;amp;quot;&amp;amp;quot;) $description = $type;&lt;br /&gt;
&lt;br /&gt;
    $cmd = $pcutils.&amp;amp;quot; publish '$port' '$description';&lt;br /&gt;
    execute_program_detached($cmd);&lt;br /&gt;
&lt;br /&gt;
    $page .= t($ipserver);&lt;br /&gt;
    $page .= par(t('Published this server.'));&lt;br /&gt;
&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Back'),'href'=&amp;amp;gt;$staticFile.'/pastecat'));&lt;br /&gt;
&lt;br /&gt;
    return($page)&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
The next thing to do will be create the function &amp;lt;code&amp;gt;publish&amp;lt;/code&amp;gt; in the controller, so we will add a new function to the basic controller we had back at section '''3.2'''. We will add a new flag called publish, so the first executed part of the script will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if [ $# -lt 1 ]&lt;br /&gt;
then&lt;br /&gt;
    doHelp&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
case $1 in&lt;br /&gt;
    &amp;amp;quot;install&amp;amp;quot;)&lt;br /&gt;
        shift&lt;br /&gt;
        doInstall $@&lt;br /&gt;
        ;;&lt;br /&gt;
    &amp;amp;quot;publish&amp;amp;quot;)&lt;br /&gt;
        shift&lt;br /&gt;
        doServer $@&lt;br /&gt;
        ;;&lt;br /&gt;
esac&amp;lt;/pre&amp;gt;&lt;br /&gt;
As we can see, when the script's first argument is &amp;lt;code&amp;gt;publish&amp;lt;/code&amp;gt;, we shift the rest of arguments and call the function &amp;lt;code&amp;gt;doServer&amp;lt;/code&amp;gt;. In this function, we must start the service with the requiered arguments, so the first thing we'll do is put the arguments into local variables. Once we do that the common thing would be to launche the Pastecat server, but since it might be called with root permissions (and this is bad) we must run it as a &amp;lt;code&amp;gt;nobody&amp;lt;/code&amp;gt; user. The issue is that the &amp;lt;code&amp;gt;nobody&amp;lt;/code&amp;gt; user has merely no permissions... and pastecat need some permissions to create folders and text files. In order to allow the &amp;lt;code&amp;gt;nobody&amp;lt;/code&amp;gt; user to do that, first of all we will create a folder and grant permissions to almost everyone to it. We will use &amp;lt;code&amp;gt;chmod&amp;lt;/code&amp;gt; again. Now, the user can create files and directories within this directory, so we can now run pastecat. Finally, we keep the pid in a variable in case we want to use it in later updates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;doServer() {&lt;br /&gt;
    # Turning machine into a server&lt;br /&gt;
&lt;br /&gt;
    local port=${1:-&amp;amp;quot;&amp;amp;quot;}&lt;br /&gt;
    local description=${2:-&amp;amp;quot;&amp;amp;quot;}&lt;br /&gt;
    local ip=${3:-&amp;amp;quot;0.0.0.0&amp;amp;quot;}&lt;br /&gt;
&lt;br /&gt;
    # Creating directory with nobody permissions&lt;br /&gt;
    mkdir -p &amp;amp;quot;/var/local/pastecat&amp;amp;quot;&lt;br /&gt;
    chmod 777 &amp;amp;quot;/var/local/pastecat&amp;amp;quot; &amp;amp;amp;&amp;amp;amp; cd &amp;amp;quot;/var/local/pastecat&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # Running pastecat &lt;br /&gt;
    cmd='su '$PCUSER' -c &amp;amp;quot;{ '$PCPATH$PCPROG' -l :'$port' &amp;amp;gt; '$LOGFILE' 2&amp;amp;gt;&amp;amp;amp;1 &amp;amp;amp; }; echo \$!&amp;amp;quot;'&lt;br /&gt;
    pidpc=$(eval $cmd)          # keeping PID for future needs...&lt;br /&gt;
&lt;br /&gt;
    cd -&lt;br /&gt;
&lt;br /&gt;
    # Using the PID, we could carry on process control so if the pastecat process die, we can also&lt;br /&gt;
    # stop the avahi process to avoid &amp;amp;quot;false connections&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that we are using some global variables that were not defined before such as &amp;lt;code&amp;gt;PCUSER&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LOGFILE&amp;lt;/code&amp;gt;. By default, we set these variables like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;PCPATH=&amp;amp;quot;/opt/pastecat/&amp;amp;quot;&lt;br /&gt;
PCPROG=&amp;amp;quot;pastecat&amp;amp;quot;&lt;br /&gt;
LOGFILE=&amp;amp;quot;/dev/null&amp;amp;quot;&lt;br /&gt;
PCUSER=&amp;amp;quot;nobody&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Stop the service =====&lt;br /&gt;
&lt;br /&gt;
Sometimes, we may also want to stop out service, so we will provide a button to do so. The first thing would be creating the button, but if we think a little, we will figure out that before doing this, we need a way to know if our service is running. In addition, we also need a way to stop our service. Since we are running on Linux, we can easily achieve that by using the &amp;lt;code&amp;gt;kill&amp;lt;/code&amp;gt; command. The thing is that to use this command, we need the Process ID (PID). Luckily for us, we already kept this number when we created the pastecat server with &amp;lt;code&amp;gt;pidpc=$(eval $cmd)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now that we have everything we need to kill our process, let's provide a way so the PHP can detect whether Pastecat is running or not. An easy and resulting way to do this is storing some useful data in a file and delete this file when pastecat is stopped. This way, we make sure that this file will only exists when Pastecat is running. This file will be created from the controller adding the following lines right below the sentence we mentioned in the previous paragraph:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Writting server info to file&lt;br /&gt;
info=&amp;amp;quot;$pidpc http://$ip:$port&amp;amp;quot;          # Separator is space character&lt;br /&gt;
echo $info &amp;amp;gt; $PCFILE&amp;lt;/pre&amp;gt;&lt;br /&gt;
where &amp;lt;code&amp;gt;$PCFILE&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;/var/run/pc.info&amp;lt;/code&amp;gt;. Note that the content of this file will be the PID and the complete direction of our Pastecat server.&lt;br /&gt;
&lt;br /&gt;
Now we have a way to know if our server is up or down, so we can add the &amp;amp;quot;stop&amp;amp;quot; button in the web interfae. We will modify a little bit the PHP script that we had before, just by addind anther advertisement indicating whether Pastecat is up or down, and 2 more buttons if it is running. So, in our index function, within the condition that checks if Pastecat is installed we will have the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$page .= &amp;amp;quot;&amp;amp;lt;div class='alert alert-success text-center'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;Pastecat is installed&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/div&amp;amp;gt;\n&amp;amp;quot;;&lt;br /&gt;
if ( isRunning() ) {&lt;br /&gt;
    $page .= &amp;amp;quot;&amp;amp;lt;div class='alert alert-success text-center'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;Pastecat is running&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/div&amp;amp;gt;\n&amp;amp;quot;;&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Go to server'),'href'=&amp;amp;gt;'http://'. getCommunityIP()['output'][0] .':'. $port));&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Stop server'),'href'=&amp;amp;gt;$staticFile.'/pastecat/stop'));&lt;br /&gt;
} else  {&lt;br /&gt;
    $page .= &amp;amp;quot;&amp;amp;lt;div class='alert alert-error text-center'&amp;amp;gt;&amp;amp;quot;.t(&amp;amp;quot;Pastecat is not running&amp;amp;quot;).&amp;amp;quot;&amp;amp;lt;/div&amp;amp;gt;\n&amp;amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
$page .= addButton(array('label'=&amp;amp;gt;t('Create a Pastecat server'),'href'=&amp;amp;gt;$staticFile.'/pastecat/publish'));&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this piece of code, we can appreciate 2 new features in our code. The first one is a check function called &amp;lt;code&amp;gt;isRunning()&amp;lt;/code&amp;gt;. This function looks very similar to the function we used to check if Pastecat is installed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function isRunning() {&lt;br /&gt;
    // Returns whether pastecat is running or not&lt;br /&gt;
    global $pcfile;&lt;br /&gt;
&lt;br /&gt;
    return(file_exists($pcfile));   &lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
It is a simple as it seems, it just checks if the file we created when starting the server still exists. The second thing we can notice in the new PHP code is the existance of a new function called &amp;lt;code&amp;gt;stop&amp;lt;/code&amp;gt;. This function will invoke another function in the controller which will stop the pastecat:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function stop() {&lt;br /&gt;
    // Stops Pastecat server&lt;br /&gt;
    global $pcpath,$pcprogram,$title,$pcutils,$avahi_type,$port;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
    $cmd = $pcutils.&amp;amp;quot; stop &amp;amp;quot;;&lt;br /&gt;
    execute_program_detached($cmd);&lt;br /&gt;
&lt;br /&gt;
    return(array('type'=&amp;amp;gt;'redirect','url'=&amp;amp;gt;$staticFile.'/pastecat'));&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
In order to make the controller understand this order, we will modify the case and add the new function. In the &amp;lt;code&amp;gt;case&amp;lt;/code&amp;gt; statement, we will add the following under the &amp;lt;code&amp;gt;install&amp;lt;/code&amp;gt; option:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;quot;stop&amp;amp;quot;)&lt;br /&gt;
    shift&lt;br /&gt;
    doStop $@&lt;br /&gt;
    ;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
This calls the function &amp;lt;code&amp;gt;doStop&amp;lt;/code&amp;gt; within the controller. This function will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;doStop() {&lt;br /&gt;
    # Stopping pastecat server&lt;br /&gt;
    pcpid=$(cat $PCFILE | cut -d' ' -f1)&lt;br /&gt;
    kill $pcpid&lt;br /&gt;
&lt;br /&gt;
    # Removing info file&lt;br /&gt;
    rm $PCFILE&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
This function just gets the pastecat's PID from the file we created before, kills the process and finally removes the file so the PHP scripts can know that pastecat is now down.&lt;br /&gt;
&lt;br /&gt;
Now we can create a pastecat instance server and stop it. However, there is still something missing: make the other users see our service. And this is why we are using avahi.&lt;br /&gt;
&lt;br /&gt;
=== Avahi service publishing ===&lt;br /&gt;
&lt;br /&gt;
On of the best things in Cloudy is the facility of publishing our service as a publication in the avahi network, allowing other users to know what we are offering and joining our service. To do this, we first need to add a few lines to the PHP controller, just after we've called the controller to start the pastecat instance. We will add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$description = str_replace(' ', '', $description);&lt;br /&gt;
$temp = avahi_publish($avahi_type, $description, $port, &amp;amp;quot;&amp;amp;quot;);&lt;br /&gt;
$page .= ptxt($temp);&amp;lt;/pre&amp;gt;&lt;br /&gt;
So in the end our function will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function _pcsource($port,$description) {&lt;br /&gt;
    global $pcpath,$pcprogram,$title,$pcutils,$avahi_type;&lt;br /&gt;
&lt;br /&gt;
    $page = &amp;amp;quot;&amp;amp;quot;;&lt;br /&gt;
    $device = getCommunityDev()['output'][0];&lt;br /&gt;
    $ipserver = getCommunityIP()['output'][0];&lt;br /&gt;
&lt;br /&gt;
    if ($description == &amp;amp;quot;&amp;amp;quot;) $description = $type;&lt;br /&gt;
&lt;br /&gt;
    $cmd = $pcutils.&amp;amp;quot; publish '$port' '$description'&amp;amp;quot;;&lt;br /&gt;
    execute_program_detached($cmd);&lt;br /&gt;
&lt;br /&gt;
    $page .= t($ipserver);&lt;br /&gt;
    $page .= par(t('Published this server.'));&lt;br /&gt;
    $description = str_replace(' ', '', $description);&lt;br /&gt;
    $temp = avahi_publish($avahi_type, $description, $port, &amp;amp;quot;&amp;amp;quot;);&lt;br /&gt;
    $page .= ptxt($temp);&lt;br /&gt;
&lt;br /&gt;
    $page .= addButton(array('label'=&amp;amp;gt;t('Back'),'href'=&amp;amp;gt;$staticFile.'/pastecat'));&lt;br /&gt;
&lt;br /&gt;
    return($page)&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
With this simple step, we announced our service in the avahi network. However the work does not end here, there is still one more thing to do: create a button and program it so when clicked, it directly goes to our pastecat server.&lt;br /&gt;
&lt;br /&gt;
To do this there is a folder called &amp;lt;code&amp;gt;avahi&amp;lt;/code&amp;gt; within the &amp;lt;code&amp;gt;plug&amp;lt;/code&amp;gt; directory. The scripts that define the function carried on when the button is clicked are defined in different files within this directory, therefor we will create a new file called &amp;lt;code&amp;gt;pastecat.avahi.PHP&amp;lt;/code&amp;gt; which will contain this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;?PHP&lt;br /&gt;
// plug/avahi/pastecat.avahi.PHP&lt;br /&gt;
&lt;br /&gt;
addAvahi('pastecat','fpcserver');&lt;br /&gt;
&lt;br /&gt;
function fpcserver($dates){&lt;br /&gt;
    global $staticFile;&lt;br /&gt;
&lt;br /&gt;
    return (&amp;amp;quot;&amp;amp;lt;a class='btn' href='http://&amp;amp;quot; .$dates['ip'] .&amp;amp;quot;:&amp;amp;quot;. $dates['port'].&amp;amp;quot;'&amp;amp;gt;Go to server&amp;amp;lt;/a&amp;amp;gt;  &amp;amp;quot;);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will create a button besides the avahi announcement line that will point to our server.&lt;br /&gt;
&lt;br /&gt;
Now that we have our service announced, we want it to dissappear when we stop the pastecat service. This last step is very simple yet important. It consist of a few lines in the PHP function called stop. Until now, this function just called the controller and stopped the pastecat, but now it will also stop the avahi publication and show a flash comment so the user knwo it worked:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$temp = avahi_unpublish($avahi_type, $port);&lt;br /&gt;
$flash = ptxt($temp);&lt;br /&gt;
setFlash($flash);&amp;lt;/pre&amp;gt;&lt;br /&gt;
These lines will be added just after the &amp;lt;code&amp;gt;execute_program_detached($cmd)&amp;lt;/code&amp;gt; sentence in the stop function.&lt;br /&gt;
&lt;br /&gt;
=== Final ===&lt;br /&gt;
&lt;br /&gt;
Finally just comment that all the files implemented in this tutorial can be found in a Github repository, linked in the External Link section, also with this tutorial in Markdown format (md).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
&lt;br /&gt;
https://github.com/Clommunity/Doc/tree/master/plugins/pastecat&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoria:Cloudy]]&lt;br /&gt;
[[ca:Cloudy_plug-ins]]&lt;br /&gt;
[[es:Cloudy_plug-ins]]&lt;/div&gt;</summary>
		<author><name>Conxuro</name></author>	</entry>

	</feed>