597 lines
32 KiB
HTML
597 lines
32 KiB
HTML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
|
<head>
|
|
<!-- 2017-07-18 Tue 11:19 -->
|
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title></title>
|
|
<meta name="generator" content="Org mode" />
|
|
<meta name="author" content="Bob Mottram" />
|
|
<meta name="description" content="Turn the Beaglebone Black into a personal communications server"
|
|
/>
|
|
<meta name="keywords" content="freedombox, debian, beaglebone, red matrix, email, web server, home server, internet, censorship, surveillance, social network, irc, jabber" />
|
|
<style type="text/css">
|
|
<!--/*--><![CDATA[/*><!--*/
|
|
.title { text-align: center;
|
|
margin-bottom: .2em; }
|
|
.subtitle { text-align: center;
|
|
font-size: medium;
|
|
font-weight: bold;
|
|
margin-top:0; }
|
|
.todo { font-family: monospace; color: red; }
|
|
.done { font-family: monospace; color: green; }
|
|
.priority { font-family: monospace; color: orange; }
|
|
.tag { background-color: #eee; font-family: monospace;
|
|
padding: 2px; font-size: 80%; font-weight: normal; }
|
|
.timestamp { color: #bebebe; }
|
|
.timestamp-kwd { color: #5f9ea0; }
|
|
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
|
|
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
|
|
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
|
|
.underline { text-decoration: underline; }
|
|
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
|
|
p.verse { margin-left: 3%; }
|
|
pre {
|
|
border: 1px solid #ccc;
|
|
box-shadow: 3px 3px 3px #eee;
|
|
padding: 8pt;
|
|
font-family: monospace;
|
|
overflow: auto;
|
|
margin: 1.2em;
|
|
}
|
|
pre.src {
|
|
position: relative;
|
|
overflow: visible;
|
|
padding-top: 1.2em;
|
|
}
|
|
pre.src:before {
|
|
display: none;
|
|
position: absolute;
|
|
background-color: white;
|
|
top: -10px;
|
|
right: 10px;
|
|
padding: 3px;
|
|
border: 1px solid black;
|
|
}
|
|
pre.src:hover:before { display: inline;}
|
|
/* Languages per Org manual */
|
|
pre.src-asymptote:before { content: 'Asymptote'; }
|
|
pre.src-awk:before { content: 'Awk'; }
|
|
pre.src-C:before { content: 'C'; }
|
|
/* pre.src-C++ doesn't work in CSS */
|
|
pre.src-clojure:before { content: 'Clojure'; }
|
|
pre.src-css:before { content: 'CSS'; }
|
|
pre.src-D:before { content: 'D'; }
|
|
pre.src-ditaa:before { content: 'ditaa'; }
|
|
pre.src-dot:before { content: 'Graphviz'; }
|
|
pre.src-calc:before { content: 'Emacs Calc'; }
|
|
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
|
|
pre.src-fortran:before { content: 'Fortran'; }
|
|
pre.src-gnuplot:before { content: 'gnuplot'; }
|
|
pre.src-haskell:before { content: 'Haskell'; }
|
|
pre.src-hledger:before { content: 'hledger'; }
|
|
pre.src-java:before { content: 'Java'; }
|
|
pre.src-js:before { content: 'Javascript'; }
|
|
pre.src-latex:before { content: 'LaTeX'; }
|
|
pre.src-ledger:before { content: 'Ledger'; }
|
|
pre.src-lisp:before { content: 'Lisp'; }
|
|
pre.src-lilypond:before { content: 'Lilypond'; }
|
|
pre.src-lua:before { content: 'Lua'; }
|
|
pre.src-matlab:before { content: 'MATLAB'; }
|
|
pre.src-mscgen:before { content: 'Mscgen'; }
|
|
pre.src-ocaml:before { content: 'Objective Caml'; }
|
|
pre.src-octave:before { content: 'Octave'; }
|
|
pre.src-org:before { content: 'Org mode'; }
|
|
pre.src-oz:before { content: 'OZ'; }
|
|
pre.src-plantuml:before { content: 'Plantuml'; }
|
|
pre.src-processing:before { content: 'Processing.js'; }
|
|
pre.src-python:before { content: 'Python'; }
|
|
pre.src-R:before { content: 'R'; }
|
|
pre.src-ruby:before { content: 'Ruby'; }
|
|
pre.src-sass:before { content: 'Sass'; }
|
|
pre.src-scheme:before { content: 'Scheme'; }
|
|
pre.src-screen:before { content: 'Gnu Screen'; }
|
|
pre.src-sed:before { content: 'Sed'; }
|
|
pre.src-sh:before { content: 'shell'; }
|
|
pre.src-sql:before { content: 'SQL'; }
|
|
pre.src-sqlite:before { content: 'SQLite'; }
|
|
/* additional languages in org.el's org-babel-load-languages alist */
|
|
pre.src-forth:before { content: 'Forth'; }
|
|
pre.src-io:before { content: 'IO'; }
|
|
pre.src-J:before { content: 'J'; }
|
|
pre.src-makefile:before { content: 'Makefile'; }
|
|
pre.src-maxima:before { content: 'Maxima'; }
|
|
pre.src-perl:before { content: 'Perl'; }
|
|
pre.src-picolisp:before { content: 'Pico Lisp'; }
|
|
pre.src-scala:before { content: 'Scala'; }
|
|
pre.src-shell:before { content: 'Shell Script'; }
|
|
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
|
|
/* additional language identifiers per "defun org-babel-execute"
|
|
in ob-*.el */
|
|
pre.src-cpp:before { content: 'C++'; }
|
|
pre.src-abc:before { content: 'ABC'; }
|
|
pre.src-coq:before { content: 'Coq'; }
|
|
pre.src-groovy:before { content: 'Groovy'; }
|
|
/* additional language identifiers from org-babel-shell-names in
|
|
ob-shell.el: ob-shell is the only babel language using a lambda to put
|
|
the execution function name together. */
|
|
pre.src-bash:before { content: 'bash'; }
|
|
pre.src-csh:before { content: 'csh'; }
|
|
pre.src-ash:before { content: 'ash'; }
|
|
pre.src-dash:before { content: 'dash'; }
|
|
pre.src-ksh:before { content: 'ksh'; }
|
|
pre.src-mksh:before { content: 'mksh'; }
|
|
pre.src-posh:before { content: 'posh'; }
|
|
/* Additional Emacs modes also supported by the LaTeX listings package */
|
|
pre.src-ada:before { content: 'Ada'; }
|
|
pre.src-asm:before { content: 'Assembler'; }
|
|
pre.src-caml:before { content: 'Caml'; }
|
|
pre.src-delphi:before { content: 'Delphi'; }
|
|
pre.src-html:before { content: 'HTML'; }
|
|
pre.src-idl:before { content: 'IDL'; }
|
|
pre.src-mercury:before { content: 'Mercury'; }
|
|
pre.src-metapost:before { content: 'MetaPost'; }
|
|
pre.src-modula-2:before { content: 'Modula-2'; }
|
|
pre.src-pascal:before { content: 'Pascal'; }
|
|
pre.src-ps:before { content: 'PostScript'; }
|
|
pre.src-prolog:before { content: 'Prolog'; }
|
|
pre.src-simula:before { content: 'Simula'; }
|
|
pre.src-tcl:before { content: 'tcl'; }
|
|
pre.src-tex:before { content: 'TeX'; }
|
|
pre.src-plain-tex:before { content: 'Plain TeX'; }
|
|
pre.src-verilog:before { content: 'Verilog'; }
|
|
pre.src-vhdl:before { content: 'VHDL'; }
|
|
pre.src-xml:before { content: 'XML'; }
|
|
pre.src-nxml:before { content: 'XML'; }
|
|
/* add a generic configuration mode; LaTeX export needs an additional
|
|
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
|
|
pre.src-conf:before { content: 'Configuration File'; }
|
|
|
|
table { border-collapse:collapse; }
|
|
caption.t-above { caption-side: top; }
|
|
caption.t-bottom { caption-side: bottom; }
|
|
td, th { vertical-align:top; }
|
|
th.org-right { text-align: center; }
|
|
th.org-left { text-align: center; }
|
|
th.org-center { text-align: center; }
|
|
td.org-right { text-align: right; }
|
|
td.org-left { text-align: left; }
|
|
td.org-center { text-align: center; }
|
|
dt { font-weight: bold; }
|
|
.footpara { display: inline; }
|
|
.footdef { margin-bottom: 1em; }
|
|
.figure { padding: 1em; }
|
|
.figure p { text-align: center; }
|
|
.inlinetask {
|
|
padding: 10px;
|
|
border: 2px solid gray;
|
|
margin: 10px;
|
|
background: #ffffcc;
|
|
}
|
|
#org-div-home-and-up
|
|
{ text-align: right; font-size: 70%; white-space: nowrap; }
|
|
textarea { overflow-x: auto; }
|
|
.linenr { font-size: smaller }
|
|
.code-highlighted { background-color: #ffff00; }
|
|
.org-info-js_info-navigation { border-style: none; }
|
|
#org-info-js_console-label
|
|
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
|
|
.org-info-js_search-highlight
|
|
{ background-color: #ffff00; color: #000000; font-weight: bold; }
|
|
.org-svg { width: 90%; }
|
|
/*]]>*/-->
|
|
</style>
|
|
<link rel="stylesheet" type="text/css" href="freedombone.css" />
|
|
<script type="text/javascript">
|
|
/*
|
|
@licstart The following is the entire license notice for the
|
|
JavaScript code in this tag.
|
|
|
|
Copyright (C) 2012-2017 Free Software Foundation, Inc.
|
|
|
|
The JavaScript code in this tag is free software: you can
|
|
redistribute it and/or modify it under the terms of the GNU
|
|
General Public License (GNU GPL) as published by the Free Software
|
|
Foundation, either version 3 of the License, or (at your option)
|
|
any later version. The code is distributed WITHOUT ANY WARRANTY;
|
|
without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
|
|
|
|
As additional permission under GNU GPL version 3 section 7, you
|
|
may distribute non-source (e.g., minimized or compacted) forms of
|
|
that code without the copy of the GNU GPL normally required by
|
|
section 4, provided you include this license notice and a URL
|
|
through which recipients can access the Corresponding Source.
|
|
|
|
|
|
@licend The above is the entire license notice
|
|
for the JavaScript code in this tag.
|
|
*/
|
|
<!--/*--><![CDATA[/*><!--*/
|
|
function CodeHighlightOn(elem, id)
|
|
{
|
|
var target = document.getElementById(id);
|
|
if(null != target) {
|
|
elem.cacheClassElem = elem.className;
|
|
elem.cacheClassTarget = target.className;
|
|
target.className = "code-highlighted";
|
|
elem.className = "code-highlighted";
|
|
}
|
|
}
|
|
function CodeHighlightOff(elem, id)
|
|
{
|
|
var target = document.getElementById(id);
|
|
if(elem.cacheClassElem)
|
|
elem.className = elem.cacheClassElem;
|
|
if(elem.cacheClassTarget)
|
|
target.className = elem.cacheClassTarget;
|
|
}
|
|
/*]]>*///-->
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div id="preamble" class="status">
|
|
<a name="top" id="top"></a>
|
|
</div>
|
|
<div id="content">
|
|
<div class="org-center">
|
|
|
|
<div class="figure">
|
|
<p><img src="images/logo.png" alt="logo.png" />
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<center><h1>Developers Guide</h1></center>
|
|
|
|
<div id="outline-container-orgeb19df0" class="outline-2">
|
|
<h2 id="orgeb19df0">Introduction</h2>
|
|
<div class="outline-text-2" id="text-orgeb19df0">
|
|
<p>
|
|
Freedombone consists of a set of bash scripts. There are a lot of them, but they're not very complicated. If you're familiar with the GNU/Linux commandline and can hack a bash script then you can probably add a new app or fix a bug in the system. There are no trendy development frameworks to learn or to get in your way.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div id="outline-container-org70ef738" class="outline-2">
|
|
<h2 id="org70ef738">Substitute for a Code of Conduct</h2>
|
|
<div class="outline-text-2" id="text-org70ef738">
|
|
<p>
|
|
Instead of having some tedious <i>Code of Conduct</i> which tries to micro-manage how folks communicate privately with each other this project has a set of guiding principles, which are as follows:
|
|
</p>
|
|
|
|
<ul class="org-ul">
|
|
<li>Enable users to help themselves to provide their own personal software infrastructure.</li>
|
|
<li>Enable users to help each other to provide software infrastructure for a community.</li>
|
|
<li>Principle of self-management: apps should require miniumum configuration and maintain themselves as far as possible.</li>
|
|
<li>There should be no single point of failure. Assume that other servers can and will fail occasionally.</li>
|
|
<li>Minimum data retention. Only store the data which users actually want or need, and within apps implement the function which allows logging to be turned off.</li>
|
|
<li>Respect other users right to run their own stuff and have their own policies on their own hardware.</li>
|
|
<li>Remove as many intermediating organisations as possible. For example, Google tracking embedded within some Free Software apps.</li>
|
|
<li>No tollbooths, rent-seeking, gatekeepers or paywalls.</li>
|
|
<li>Maximize energy efficiency. No systems which fundamentally depend upon proof-of-work block solving or other compute-heavy methods. The target here is small single board computers.</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-orgce166ed" class="outline-2">
|
|
<h2 id="orgce166ed">Adding extra apps</h2>
|
|
<div class="outline-text-2" id="text-orgce166ed">
|
|
<p>
|
|
Suppose you have some internet application which you want to add to the system. To do this you need to create an app script which tells the system how to install/remove and also backup/restore. The script should be designed to work with the current stable version of Debian.
|
|
</p>
|
|
|
|
<p>
|
|
On an installed system the app scripts go into the directory:
|
|
</p>
|
|
|
|
<div class="org-src-container">
|
|
<pre><code class="src src-bash">/usr/share/freedombone/apps
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>
|
|
and within the project repo they appear within the <i>src</i> directory. Your new app script should have the name:
|
|
</p>
|
|
|
|
<div class="org-src-container">
|
|
<pre><code class="src src-bash">freedombone-app-[myappname]
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>
|
|
The <i>myappname</i> value should not contain any spaces and will appear in the list of available apps.
|
|
</p>
|
|
|
|
<p>
|
|
An example template for an app script is shown below. Copy this and add whatever variables and configuration you need. Search and replace <i>myappname</i> with your own.
|
|
</p>
|
|
|
|
<div class="org-src-container">
|
|
<pre><code class="src src-bash"><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/</span><span class="org-keyword">bash</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Copyright (C) Year YourName <YourEmail></span>
|
|
<span class="org-comment-delimiter">#</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">This program is free software: you can redistribute it</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">and/or modify it under the terms of the GNU Affero General</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Public License as published by the Free Software Foundation,</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">either version 3 of the License, or (at your option) any</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">later version.</span>
|
|
<span class="org-comment-delimiter">#</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">This program is distributed in the hope that it will be useful,</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">GNU Affero General Public License for more details.</span>
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">'full' includes your app in the full installation and you</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">can also add other variants, separated by spaces. The</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">available variants will be detected automatically from the</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">app scripts. In most cases don't change this.</span>
|
|
<span class="org-variable-name">VARIANTS</span>=<span class="org-string">'full'</span>
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If you want this to appear on the control panel About screen</span>
|
|
<span class="org-variable-name">SHOW_ON_ABOUT</span>=1
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If you want this app to be in the default installation,</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">otherwise it will be available but not selected by default</span>
|
|
<span class="org-variable-name">IN_DEFAULT_INSTALL</span>=1
|
|
|
|
<span class="org-variable-name">SOME_IMPORTANT_CONFIG_VARIABLE</span>=<span class="org-string">'some important value'</span>
|
|
<span class="org-variable-name">ANOTHER_IMPORTANT_CONFIG_VARIABLE</span>=<span class="org-string">'foo'</span>
|
|
<span class="org-variable-name">MY_FUNKY_AVATAR</span>=https://some-domain-or-other/fro.png
|
|
<span class="org-variable-name">MYAPPNAME_ONION_PORT</span>=[port number]
|
|
<span class="org-variable-name">MYAPPNAME_DB_PASSWORD</span>=
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">A directory where the data for this app exists</span>
|
|
<span class="org-variable-name">MYAPP_DATA_DIR</span>=/var/lib/somedirectory
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">List of configuration variables used by the app</span>
|
|
<span class="org-variable-name">myappname_variables</span>=(ONION_ONLY
|
|
MY_USERNAME
|
|
SOME_IMPORTANT_CONFIG_VARIABLE
|
|
ANOTHER_IMPORTANT_CONFIG_VARIABLE
|
|
MY_FUNKY_AVATAR
|
|
MYAPPNAME_ONION_PORT
|
|
MYAPPNAME_DB_PASSWORD)
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">logging_on_myappname</span> {
|
|
<span class="org-builtin">echo</span> -n <span class="org-string">''</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Commands to turn on logging go here</span>
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">logging_off_myappname</span> {
|
|
<span class="org-builtin">echo</span> -n <span class="org-string">''</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Commands to turn off logging go here</span>
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">change_password_myappname</span> {
|
|
<span class="org-variable-name">PASSWORD_USERNAME</span>=<span class="org-string">"$1"</span>
|
|
<span class="org-variable-name">PASSWORD_NEW</span>=<span class="org-string">"$2"</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Do something to change the password</span>
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">reconfigure_myappname</span> {
|
|
<span class="org-builtin">echo</span> -n <span class="org-string">''</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Do something to delete existing keys/identity and</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">generate new ones</span>
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">upgrade_myappname</span> {
|
|
<span class="org-builtin">echo</span> -n <span class="org-string">''</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Do something to upgrade this app.</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If it's a debian package then it will be maintained by the</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">operating system and you don't need anything here</span>
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">backup_local_myappname</span> {
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If your app has a MariaDB/MySQL database</span>
|
|
backup_database_to_usb myappname
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">To backup a directory</span>
|
|
backup_directory_to_usb $<span class="org-variable-name">MYAPP_DATA_DIR</span> myappname
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">if you need to backup data within individual user</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">home directories</span>
|
|
<span class="org-keyword">for</span> d<span class="org-keyword"> in</span> /home/*/ ; <span class="org-keyword">do</span>
|
|
<span class="org-variable-name">USERNAME</span>=$(<span class="org-sh-quoted-exec">echo</span> <span class="org-string">"$d"</span> | awk -F <span class="org-string">'/'</span> <span class="org-string">'{print $3}'</span>)
|
|
<span class="org-keyword">if</span> [[ $(<span class="org-sh-quoted-exec">is_valid_user</span> <span class="org-string">"$USERNAME"</span>) == <span class="org-string">"1"</span> ]]; <span class="org-keyword">then</span>
|
|
<span class="org-builtin">echo</span> $<span class="org-string">"Backing up myappname config for $USERNAME"</span>
|
|
<span class="org-keyword">if</span> [ -d /home/$<span class="org-variable-name">USERNAME</span>/.config/myappname ]; <span class="org-keyword">then</span>
|
|
backup_directory_to_usb <span class="org-sh-escaped-newline">\</span>
|
|
/home/$<span class="org-variable-name">USERNAME</span>/.config/myappname <span class="org-sh-escaped-newline">\</span>
|
|
myappname_users/$<span class="org-variable-name">USERNAME</span>
|
|
<span class="org-keyword">fi</span>
|
|
<span class="org-keyword">fi</span>
|
|
<span class="org-keyword">done</span>
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">restore_local_myappname</span> {
|
|
<span class="org-variable-name">temp_restore_dir</span>=/root/tempmyappname
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If your app has a MariaDB/MySQL database</span>
|
|
restore_database myappname
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Restore some data from a directory</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Note that we don't restore directly but to a temporary</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">directory and then copy the files. This ensures that if</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">there is a restore failure you don't end up with</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">half-copied or corrupted files</span>
|
|
restore_directory_from_usb $<span class="org-variable-name">MYAPP_DATA_DIR</span> myappname
|
|
cp -r $<span class="org-variable-name">temp_restore_dir</span>/$<span class="org-variable-name">MYAPP_DATA_DIR</span> $<span class="org-variable-name">MYAPP_DATA_DIR</span>
|
|
rm -rf $<span class="org-variable-name">temp_restore_dir</span>
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If you need to restore a configuration directory for each user</span>
|
|
<span class="org-keyword">if</span> [ -d $<span class="org-variable-name">USB_MOUNT</span>/backup/myappname_users ]; <span class="org-keyword">then</span>
|
|
<span class="org-keyword">for</span> d<span class="org-keyword"> in</span> $<span class="org-variable-name">USB_MOUNT</span>/backup/myappname_users/*/ ; <span class="org-keyword">do</span>
|
|
<span class="org-variable-name">USERNAME</span>=$(<span class="org-sh-quoted-exec">echo</span> <span class="org-string">"$d"</span> | awk -F <span class="org-string">'/'</span> <span class="org-string">'{print $6}'</span>)
|
|
<span class="org-keyword">if</span> [[ $(<span class="org-sh-quoted-exec">is_valid_user</span> <span class="org-string">"$USERNAME"</span>) == <span class="org-string">"1"</span> ]]; <span class="org-keyword">then</span>
|
|
<span class="org-keyword">if</span> [ <span class="org-negation-char">!</span> -d /home/$<span class="org-variable-name">USERNAME</span> ]; <span class="org-keyword">then</span>
|
|
${<span class="org-variable-name">PROJECT_NAME</span>}-adduser $<span class="org-variable-name">USERNAME</span>
|
|
<span class="org-keyword">fi</span>
|
|
<span class="org-builtin">echo</span> $<span class="org-string">"Restoring Vim config for $USERNAME"</span>
|
|
function_check restore_directory_from_usb
|
|
restore_directory_from_usb $<span class="org-variable-name">temp_restore_dir</span> <span class="org-sh-escaped-newline">\</span>
|
|
myappname_users/$<span class="org-variable-name">USERNAME</span>
|
|
cp -r $<span class="org-variable-name">temp_restore_dir</span>/home/$<span class="org-variable-name">USERNAME</span>/.config <span class="org-sh-escaped-newline">\</span>
|
|
/home/$<span class="org-variable-name">USERNAME</span>/
|
|
<span class="org-keyword">if</span> [ <span class="org-negation-char">!</span> <span class="org-string">"$?"</span> = <span class="org-string">"0"</span> ]; <span class="org-keyword">then</span>
|
|
rm -rf $<span class="org-variable-name">temp_restore_dir</span>
|
|
set_user_permissions
|
|
backup_unmount_drive
|
|
<span class="org-keyword">exit</span> 664
|
|
<span class="org-keyword">fi</span>
|
|
rm -rf $<span class="org-variable-name">temp_restore_dir</span>
|
|
<span class="org-keyword">fi</span>
|
|
<span class="org-keyword">done</span>
|
|
<span class="org-keyword">fi</span>
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">backup_remote_myappname</span> {
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">this should be the same as backup_local_myappname,</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">but call the backup functions backup_directory_to_friend</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">and backup_database_to_friend</span>
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">restore_remote_vim</span> {
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">this should be the same as restore_local_myappname,</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">but call the restore function restore_directory_from_friend</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">and restore_database_from_friend</span>
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">remove_myappname</span> {
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">if it's a debian package then:</span>
|
|
apt-get -y remove --purge [my-app-package-name]
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If your app has a MariaDB/MySQL database</span>
|
|
drop_database myappname
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If your app uses an onion address</span>
|
|
remove_onion_service myappname ${<span class="org-variable-name">MYAPPNAME_ONION_PORT</span>}
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">install_myappname</span> {
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">if it's a debian package then:</span>
|
|
apt-get -y install [my-app-package-name]
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If you need to create a MariaDB/MySQL database for the app</span>
|
|
<span class="org-variable-name">MYAPPNAME_DB_PASSWORD</span>=<span class="org-string">"$(</span><span class="org-sh-quoted-exec">create_password</span><span class="org-string"> 20)"</span>
|
|
create_database myappname <span class="org-string">"$MYAPPNAME_DB_PASSWORD"</span> $<span class="org-variable-name">MY_USERNAME</span>
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If you need to create an onion address for the app</span>
|
|
<span class="org-variable-name">MYAPPNAME_ONION_HOSTNAME</span>=$(<span class="org-sh-quoted-exec">add_onion_service</span> myappname <span class="org-sh-escaped-newline">\</span>
|
|
80 ${<span class="org-variable-name">MYAPPNAME_ONION_PORT</span>})
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Do any other configuration</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Here you might use $ONION_ONLY or</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">$SOME_IMPORTANT_CONFIG_VARIABLE</span>
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Mark the app as having installed successfully</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">If this variable isn't set then it will be assumed that</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">the install has failed</span>
|
|
<span class="org-variable-name">APP_INSTALLED</span>=1
|
|
}
|
|
|
|
<span class="org-keyword">function</span> <span class="org-function-name">install_interactive_myappname</span> {
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">Interactively obtain some values using dialog, such as</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">domain names. An avatar changing example is:</span>
|
|
<span class="org-variable-name">data</span>=$(<span class="org-sh-quoted-exec">tempfile</span> 2>/dev/null)
|
|
<span class="org-keyword">trap</span> <span class="org-string">"rm -f $data"</span> 0 1 2 5 15
|
|
dialog --title $<span class="org-string">"Change your avatar"</span> <span class="org-sh-escaped-newline">\</span>
|
|
--backtitle $<span class="org-string">"Freedombone Control Panel"</span> <span class="org-sh-escaped-newline">\</span>
|
|
--inputbox $<span class="org-string">"Enter a URL for an image. It should be "</span> <span class="org-sh-escaped-newline">\</span>
|
|
$<span class="org-string">"approximately a square image."</span> 8 75 2>$<span class="org-variable-name">data</span>
|
|
<span class="org-variable-name">sel</span>=$<span class="org-variable-name">?</span>
|
|
<span class="org-keyword">case</span> $<span class="org-variable-name">sel</span><span class="org-keyword"> in</span>
|
|
0)
|
|
<span class="org-variable-name">MY_FUNKY_AVATAR</span>=$(<$<span class="org-variable-name">data</span>)
|
|
<span class="org-keyword">if</span> [ ${#<span class="org-variable-name">MY_FUNKY_AVATAR</span>} -gt 3 ]; <span class="org-keyword">then</span>
|
|
clear
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">do whatever is needed to change the avatar</span>
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">in your app</span>
|
|
|
|
dialog --title $<span class="org-string">"Change your avatar"</span> <span class="org-sh-escaped-newline">\</span>
|
|
--msgbox $<span class="org-string">"Your avatar has been changed"</span> 6 40
|
|
<span class="org-keyword">fi</span>
|
|
;;
|
|
<span class="org-keyword">esac</span>
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">install_myappname will be called automatically after this function</span>
|
|
}
|
|
|
|
<span class="org-comment-delimiter"># </span><span class="org-comment">NOTE: deliberately no exit 0</span>
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>
|
|
To test your app log into your system, select <b>Exit to command line</b> then gain root powers with:
|
|
</p>
|
|
|
|
<div class="org-src-container">
|
|
<pre><code class="src src-bash">sudo su
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>
|
|
Copy your app script to <b>/usr/share/freedombone/apps/freedombone-app-myappname</b>.
|
|
</p>
|
|
|
|
<p>
|
|
And run the admin control panel:
|
|
</p>
|
|
|
|
<div class="org-src-container">
|
|
<pre><code class="src src-bash">control
|
|
</code></pre>
|
|
</div>
|
|
|
|
<p>
|
|
Select <b>Add/Remove Apps</b> and if all is well then you should see your app listed as installable. Test that installing and removing it works as expected.
|
|
</p>
|
|
|
|
<p>
|
|
Submit your working app to <b><a href="https://github.com/bashrc/freedombone/issues">https://github.com/bashrc/freedombone/issues</a></b>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="outline-container-org2e7b384" class="outline-2">
|
|
<h2 id="org2e7b384">Customising mesh images</h2>
|
|
<div class="outline-text-2" id="text-org2e7b384">
|
|
<p>
|
|
If you want to make your own specially branded version of the mesh images, such as for a particular event, then to change the default desktop backgrounds edit the images within <b>img/backgrounds</b> and to change the available avatars and desktop icons edit the images within <b>img/avatars</b>. Re-create disk images using the instructions shown previously.
|
|
</p>
|
|
|
|
<p>
|
|
If you need particular <i>dconf</i> commands to alter desktop appearance or behavior then see the function <i>mesh_client_startup_applications</i> within <b>src/freedombone-image-customise</b>.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="postamble" class="status">
|
|
|
|
<style type="text/css">
|
|
.back-to-top {
|
|
position: fixed;
|
|
bottom: 2em;
|
|
right: 0px;
|
|
text-decoration: none;
|
|
color: #000000;
|
|
background-color: rgba(235, 235, 235, 0.80);
|
|
font-size: 12px;
|
|
padding: 1em;
|
|
display: none;
|
|
}
|
|
|
|
.back-to-top:hover {
|
|
background-color: rgba(135, 135, 135, 0.50);
|
|
}
|
|
</style>
|
|
|
|
<div class="back-to-top">
|
|
<a href="#top">Back to top</a> | <a href="mailto:bob@freedombone.net">E-mail me</a>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|