瀏覽代碼

Merge branch 'stretch' of https://github.com/bashrc/freedombone

Bob Mottram 7 年之前
父節點
當前提交
8d4dd741ed
共有 5 個檔案被更改,包括 333 行新增528 行删除
  1. 45
    220
      doc/EN/devguide.org
  2. 二進制
      man/freedombone-template.1.gz
  3. 2
    2
      src/freedombone-app-nextcloud
  4. 221
    75
      src/freedombone-template
  5. 65
    231
      website/EN/devguide.html

+ 45
- 220
doc/EN/devguide.org 查看文件

@@ -15,257 +15,82 @@
15 15
 #+end_export
16 16
 
17 17
 * Introduction
18
-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. You might also want to consult the [[./codeofconduct.html][Code of Conduct]].
18
+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. You might also want to consult the [[./codeofconduct.html][Code of Conduct]], and there is a Matrix room at *#fbone:matrix.freedombone.net*
19 19
 * Adding extra apps
20 20
 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.
21 21
 
22
-On an installed system the app scripts go into the directory:
22
+There's a command which you can use to generate scripts for new apps. Some examples are as follows:
23
+
24
+To create a script for a generic PHP plus MySql/MariaDB web app:
23 25
 
24 26
 #+begin_src bash
25
-/usr/share/freedombone/apps
27
+freedombone-template --app [name] -e [email] -r [repo url] \
28
+                     -c [commit] --php yes -d mariadb > \
29
+                     src/freedombone-app-myappname
26 30
 #+end_src
27 31
 
28
-and within the project repo they appear within the /src/ directory. Your new app script should have the name:
32
+For a Nodejs app with MySql/MariaDB database:
29 33
 
30 34
 #+begin_src bash
31
-freedombone-app-[myappname]
35
+freedombone-template --app [name] -e [email] -r [repo url] \
36
+                     -c [commit] --node yes -d mariadb \
37
+                     --dir /etc/myappname --daemon yes > \
38
+                     src/freedombone-app-myappname
32 39
 #+end_src
33 40
 
34
-The /myappname/ value should not contain any spaces and will appear in the list of available apps.
35
-
36
-An example template for an app script is shown below. Copy this and add whatever variables and configuration you need. Search and replace /myappname/ with your own.
41
+For a Python app with Postgresql database:
37 42
 
38 43
 #+begin_src bash
39
-#!/bin/bash
40
-# Copyright (C) Year YourName <YourEmail>
41
-#
42
-# This program is free software: you can redistribute it
43
-# and/or modify it under the terms of the GNU Affero General
44
-# Public License as published by the Free Software Foundation,
45
-# either version 3 of the License, or (at your option) any
46
-# later version.
47
-#
48
-# This program is distributed in the hope that it will be useful,
49
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
50
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
51
-# GNU Affero General Public License for more details.
52
-
53
-# 'full' includes your app in the full installation and you
54
-# can also add other variants, separated by spaces. The
55
-# available variants will be detected automatically from the
56
-# app scripts. In most cases don't change this.
57
-VARIANTS='full'
58
-
59
-# If you want this to appear on the control panel About screen
60
-SHOW_ON_ABOUT=1
61
-
62
-# If you want this app to be in the default installation,
63
-# otherwise it will be available but not selected by default
64
-IN_DEFAULT_INSTALL=1
65
-
66
-SOME_IMPORTANT_CONFIG_VARIABLE='some important value'
67
-ANOTHER_IMPORTANT_CONFIG_VARIABLE='foo'
68
-MY_FUNKY_AVATAR=https://some-domain-or-other/fro.png
69
-MYAPPNAME_ONION_PORT=[port number]
70
-MYAPPNAME_DB_PASSWORD=
71
-
72
-# A directory where the data for this app exists
73
-MYAPP_DATA_DIR=/var/lib/somedirectory
74
-
75
-# List of configuration variables used by the app
76
-myappname_variables=(ONION_ONLY
77
-                     MY_USERNAME
78
-                     SOME_IMPORTANT_CONFIG_VARIABLE
79
-                     ANOTHER_IMPORTANT_CONFIG_VARIABLE
80
-                     MY_FUNKY_AVATAR
81
-                     MYAPPNAME_ONION_PORT
82
-                     MYAPPNAME_DB_PASSWORD)
83
-
84
-function logging_on_myappname {
85
-    echo -n ''
86
-    # Commands to turn on logging go here
87
-}
88
-
89
-function logging_off_myappname {
90
-    echo -n ''
91
-    # Commands to turn off logging go here
92
-}
93
-
94
-function change_password_myappname {
95
-    PASSWORD_USERNAME="$1"
96
-    PASSWORD_NEW="$2"
97
-    # Do something to change the password
98
-}
99
-
100
-function reconfigure_myappname {
101
-    echo -n ''
102
-    # Do something to delete existing keys/identity and
103
-    # generate new ones
104
-}
105
-
106
-function upgrade_myappname {
107
-    echo -n ''
108
-    # Do something to upgrade this app.
109
-    # If it's a debian package then it will be maintained by the
110
-    # operating system and you don't need anything here
111
-}
112
-
113
-function backup_local_myappname {
114
-    # If your app has a MariaDB/MySQL database
115
-    backup_database_to_usb myappname
116
-
117
-    # To backup a directory
118
-    backup_directory_to_usb $MYAPP_DATA_DIR myappname
119
-
120
-    # if you need to backup data within individual user
121
-    # home directories
122
-    for d in /home/*/ ; do
123
-        USERNAME=$(echo "$d" | awk -F '/' '{print $3}')
124
-        if [[ $(is_valid_user "$USERNAME") == "1" ]]; then
125
-            echo $"Backing up myappname config for $USERNAME"
126
-            if [ -d /home/$USERNAME/.config/myappname ]; then
127
-                backup_directory_to_usb \
128
-                    /home/$USERNAME/.config/myappname \
129
-                    myappname_users/$USERNAME
130
-            fi
131
-        fi
132
-    done
133
-}
134
-
135
-function restore_local_myappname {
136
-    temp_restore_dir=/root/tempmyappname
137
-
138
-    # If your app has a MariaDB/MySQL database
139
-    restore_database myappname
140
-
141
-    # Restore some data from a directory
142
-    # Note that we don't restore directly but to a temporary
143
-    # directory and then copy the files. This ensures that if
144
-    # there is a restore failure you don't end up with
145
-    # half-copied or corrupted files
146
-    restore_directory_from_usb $MYAPP_DATA_DIR myappname
147
-    cp -r $temp_restore_dir/$MYAPP_DATA_DIR $MYAPP_DATA_DIR
148
-    rm -rf $temp_restore_dir
149
-
150
-    # If you need to restore a configuration directory for each user
151
-    if [ -d $USB_MOUNT/backup/myappname_users ]; then
152
-        for d in $USB_MOUNT/backup/myappname_users/*/ ; do
153
-            USERNAME=$(echo "$d" | awk -F '/' '{print $6}')
154
-            if [[ $(is_valid_user "$USERNAME") == "1" ]]; then
155
-                if [ ! -d /home/$USERNAME ]; then
156
-                    ${PROJECT_NAME}-adduser $USERNAME
157
-                fi
158
-                echo $"Restoring Vim config for $USERNAME"
159
-                function_check restore_directory_from_usb
160
-                restore_directory_from_usb $temp_restore_dir \
161
-                                           myappname_users/$USERNAME
162
-                cp -r $temp_restore_dir/home/$USERNAME/.config \
163
-                      /home/$USERNAME/
164
-                if [ ! "$?" = "0" ]; then
165
-                    rm -rf $temp_restore_dir
166
-                    set_user_permissions
167
-                    backup_unmount_drive
168
-                    exit 664
169
-                fi
170
-                rm -rf $temp_restore_dir
171
-            fi
172
-        done
173
-    fi
174
-}
175
-
176
-function backup_remote_myappname {
177
-    # this should be the same as backup_local_myappname,
178
-    # but call the backup functions backup_directory_to_friend
179
-    # and backup_database_to_friend
180
-}
181
-
182
-function restore_remote_vim {
183
-    # this should be the same as restore_local_myappname,
184
-    # but call the restore function restore_directory_from_friend
185
-    # and restore_database_from_friend
186
-}
187
-
188
-function remove_myappname {
189
-    # if it's a debian package then:
190
-    apt-get -y remove --purge [my-app-package-name]
191
-
192
-    # If your app has a MariaDB/MySQL database
193
-    drop_database myappname
194
-
195
-    # If your app uses an onion address
196
-    remove_onion_service myappname ${MYAPPNAME_ONION_PORT}
197
-}
198
-
199
-function install_myappname {
200
-    # if it's a debian package then:
201
-    apt-get -y install [my-app-package-name]
202
-
203
-    # If you need to create a MariaDB/MySQL database for the app
204
-    MYAPPNAME_DB_PASSWORD="$(create_password 20)"
205
-    create_database myappname "$MYAPPNAME_DB_PASSWORD" $MY_USERNAME
206
-
207
-    # If you need to create an onion address for the app
208
-    MYAPPNAME_ONION_HOSTNAME=$(add_onion_service myappname \
209
-                               80 ${MYAPPNAME_ONION_PORT})
210
-
211
-    # Do any other configuration
212
-    # Here you might use $ONION_ONLY or
213
-    # $SOME_IMPORTANT_CONFIG_VARIABLE
44
+freedombone-template --app [name] -e [email] -r [repo url] \
45
+                     -c [commit] -d postgresql \
46
+                     --dir /etc/myappname --daemon yes > \
47
+                     src/freedombone-app-myappname
48
+#+end_src
214 49
 
215
-    # Mark the app as having installed successfully
216
-    # If this variable isn't set then it will be assumed that
217
-    # the install has failed
218
-    APP_INSTALLED=1
219
-}
50
+For a Python app without any database, communicating between the daemon and the web server on port 1234:
220 51
 
221
-function install_interactive_myappname {
222
-    # Interactively obtain some values using dialog, such as
223
-    # domain names. An avatar changing example is:
224
-    data=$(tempfile 2>/dev/null)
225
-    trap "rm -f $data" 0 1 2 5 15
226
-    dialog --title $"Change your avatar" \
227
-           --backtitle $"Freedombone Control Panel" \
228
-           --inputbox $"Enter a URL for an image. It should be " \
229
-                      $"approximately a square image." 8 75 2>$data
230
-    sel=$?
231
-    case $sel in
232
-        0)
233
-            MY_FUNKY_AVATAR=$(<$data)
234
-            if [ ${#MY_FUNKY_AVATAR} -gt 3 ]; then
235
-                clear
52
+#+begin_src bash
53
+freedombone-template --app [name] -e [email] -r [repo url] \
54
+                     -c [commit] --dir /etc/myappname \
55
+                     --daemon yes --portinternal 1234 > \
56
+                     src/freedombone-app-myappname
57
+#+end_src
236 58
 
237
-                # do whatever is needed to change the avatar
238
-                # in your app
59
+For an app without any database which communicates directly on a particular port through the firewall:
239 60
 
240
-                dialog --title $"Change your avatar" \
241
-                       --msgbox $"Your avatar has been changed" 6 40
242
-            fi
243
-            ;;
244
-    esac
61
+#+begin_src bash
62
+freedombone-template --app [name] -e [email] -r [repo url] \
63
+                     -c [commit] --dir /etc/myappname \
64
+                     --daemon yes --port 5000 > \
65
+                     src/freedombone-app-myappname
66
+#+end_src
245 67
 
246
-    # install_myappname will be called automatically after this function
247
-}
68
+A generic PHP plus MySql/MariaDB web app which is only available on an onion address:
248 69
 
249
-# NOTE: deliberately no exit 0
70
+#+begin_src bash
71
+freedombone-template --app [name] -e [email] -r [repo url] \
72
+                     -c [commit] --php yes -d mariadb \
73
+                     --onion yes > \
74
+                     src/freedombone-app-myappname
250 75
 #+end_src
251 76
 
252
-To test your app log into your system, select *Exit to command line* then gain root powers with:
77
+For more details see the manpage:
253 78
 
254 79
 #+begin_src bash
255
-sudo su
80
+man freedombone-template
256 81
 #+end_src
257 82
 
258
-Copy your app script to */usr/share/freedombone/apps/freedombone-app-myappname*.
83
+The template command won't give you a fully working app, but it will give you a big head start and avoid a lot of potential mistakes. It's highly likely that you'll still need to add extra configuration for your particular app, especially within the *install_app* function.
259 84
 
260
-And run the admin control panel:
85
+When your new script is ready for testing you can install it with:
261 86
 
262 87
 #+begin_src bash
263
-control
88
+make install
264 89
 #+end_src
265 90
 
266
-Select *Add/Remove Apps* and if all is well then you should see your app listed as installable. Test that installing and removing it works as expected.
91
+Then run the administrator control panel and you should see the new app within *Add/Remove apps*.
267 92
 
268
-Submit your working app to *https://github.com/bashrc/freedombone/issues*
93
+Submit your working app to *https://github.com/bashrc/freedombone/issues* or create a pull request.
269 94
 
270 95
 * Customising mesh images
271 96
 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 *img/backgrounds* and to change the available avatars and desktop icons edit the images within *img/avatars*. Re-create disk images using the instructions shown previously.

二進制
man/freedombone-template.1.gz 查看文件


+ 2
- 2
src/freedombone-app-nextcloud 查看文件

@@ -39,8 +39,8 @@ NEXTCLOUD_DOMAIN_NAME=
39 39
 NEXTCLOUD_CODE=
40 40
 NEXTCLOUD_ONION_PORT=8112
41 41
 NEXTCLOUD_REPO="https://github.com/nextcloud/server"
42
-# Stable 12 branch
43
-NEXTCLOUD_COMMIT='cd095bb0b85eed6a9a9f6f0f7d10f2366c4667a7'
42
+# Stable 13 branch
43
+NEXTCLOUD_COMMIT='b16824db31cd00e26e72216bf995d52389b9c93c'
44 44
 NEXTCLOUD_ADMIN_PASSWORD=
45 45
 
46 46
 nextcloud_variables=(ONION_ONLY

+ 221
- 75
src/freedombone-template 查看文件

@@ -31,13 +31,19 @@
31 31
 PROJECT_NAME='freedombone'
32 32
 
33 33
 app_name='noapp'
34
-app_name_lower="$(tr '[:upper:]' '[:lower:]' <<< ${app_name:0:1})${app_name:1}"
34
+app_name_lower=$(echo ${app_name} | tr '[:upper:]' '[:lower:]')
35 35
 app_name=$app_name_lower
36
-app_name_upper="$(tr '[:lower:]' '[:upper:]' <<< ${app_name:0:1})${app_name:1}"
36
+app_name_upper=$(echo ${app_name} | tr '[:lower:]' '[:upper:]')
37
+echo "test: $app_name_upper"
37 38
 app_repo="TODO"
38 39
 app_repo_commit='TODO'
39 40
 app_php=
40 41
 app_node=
42
+app_onion_only=
43
+app_port=
44
+app_port_internal=
45
+app_daemon=
46
+app_dir=
41 47
 your_name=''
42 48
 your_email=''
43 49
 SHOW_ON_ABOUT=1
@@ -56,9 +62,14 @@ function show_help {
56 62
     echo $'  -e --email [address]                 Your email address'
57 63
     echo $'  -r --repo [url]                      Git repo url for the app'
58 64
     echo $'  -c --commit [hash]                   Git commit'
65
+    echo $'     --port [number]                   Port number for the app'
66
+    echo $'     --portinternal [number]           Internal port between a daemon and the web server'
59 67
     echo $'     --node [yes|no]                   Is this a nodejs app?'
68
+    echo $'  -o --onion [yes|no]                  Is this app only available on an onion address?'
60 69
     echo $'  -p --php [yes|no]                    Is this a PHP app?'
70
+    echo $'  -s --daemon [yes|no]                 Add a daemon'
61 71
     echo $'  -d --database [mariadb|postgresql]   Type of database'
72
+    echo $'     --dir [directory]                 Where to install to'
62 73
     echo ''
63 74
     exit 0
64 75
 }
@@ -74,9 +85,9 @@ do
74 85
         -a|--app|--appname)
75 86
             shift
76 87
             app_name="$1"
77
-            app_name_lower="$(tr '[:upper:]' '[:lower:]' <<< ${app_name:0:1})${app_name:1}"
88
+            app_name_lower=$(echo ${app_name} | tr '[:upper:]' '[:lower:]')
78 89
             app_name=$app_name_lower
79
-            app_name_upper="$(tr '[:lower:]' '[:upper:]' <<< ${app_name:0:1})${app_name:1}"
90
+            app_name_upper=$(echo ${app_name} | tr '[:lower:]' '[:upper:]')
80 91
             ;;
81 92
         -r|--repo)
82 93
             shift
@@ -106,6 +117,30 @@ do
106 117
             shift
107 118
             app_node="$1"
108 119
             ;;
120
+        -s|--daemon|--systemd)
121
+            shift
122
+            if [[ "$1" == 'yes' ]]; then
123
+                app_daemon=1
124
+            fi
125
+            ;;
126
+        -o|--onion)
127
+            shift
128
+            if [[ "$1" == 'yes' ]]; then
129
+                app_onion_only=1
130
+            fi
131
+            ;;
132
+        --port)
133
+            shift
134
+            app_port="$1"
135
+            ;;
136
+        --portinternal|--portint)
137
+            shift
138
+            app_port_internal="$1"
139
+            ;;
140
+        --dir)
141
+            shift
142
+            app_dir="$1"
143
+            ;;
109 144
         *)
110 145
             # unknown option
111 146
             ;;
@@ -185,12 +220,25 @@ echo "VARIANTS='full full-vim'"
185 220
 echo ''
186 221
 echo 'IN_DEFAULT_INSTALL=0'
187 222
 echo "SHOW_ON_ABOUT=${SHOW_ON_ABOUT}"
223
+if [ $app_onion_only ]; then
224
+    echo 'SHOW_ICANN_ADDRESS_ON_ABOUT=0'
225
+fi
188 226
 echo ''
189 227
 echo "${app_name_upper}_DOMAIN_NAME="
190 228
 echo "${app_name_upper}_CODE="
229
+if [ $app_port ]; then
230
+    echo "${app_name_upper}_PORT=$app_port"
231
+fi
191 232
 echo "${app_name_upper}_ONION_PORT=$(( ( RANDOM % 1000 )  + 9010 ))"
192 233
 echo "${app_name_upper}_REPO=\"${app_repo}\""
193 234
 echo "${app_name_upper}_COMMIT='${app_repo_commit}'"
235
+if [ $app_daemon ]; then
236
+    if [ ! $app_port_internal ]; then
237
+        echo "${app_name_upper}_PORT_INTERNAL=TODO"
238
+    else
239
+        echo "${app_name_upper}_PORT_INTERNAL=$app_port_internal"
240
+    fi
241
+fi
194 242
 echo ''
195 243
 echo "${app_name}=(ONION_ONLY"
196 244
 echo "             ${app_name_upper}_DOMAIN_NAME"
@@ -221,16 +269,20 @@ echo "    echo '0'"
221 269
 echo '}'
222 270
 echo ''
223 271
 echo "function install_interactive_${app_name} {"
224
-echo '    if [ ! $ONION_ONLY ]; then'
225
-echo "        ONION_ONLY='no'"
226
-echo '    fi'
227
-echo ''
228
-echo '    if [[ $ONION_ONLY != "no" ]]; then'
229
-echo "        ${app_name_upper}_DOMAIN_NAME='${app_name}.local'"
230
-echo "        write_config_param \"${app_name_upper}_DOMAIN_NAME\" \"\$${app_name_upper}_DOMAIN_NAME\""
231
-echo '    else'
232
-echo "        interactive_site_details \"${app_name}\" \"${app_name_upper}_DOMAIN_NAME\" \"${app_name}_CODE\""
233
-echo '    fi'
272
+if [ ! $app_onion_only ]; then
273
+    echo '    if [ ! $ONION_ONLY ]; then'
274
+    echo "        ONION_ONLY='no'"
275
+    echo '    fi'
276
+    echo ''
277
+    echo '    if [[ $ONION_ONLY != "no" ]]; then'
278
+    echo "        ${app_name_upper}_DOMAIN_NAME='${app_name}.local'"
279
+    echo "        write_config_param \"${app_name_upper}_DOMAIN_NAME\" \"\$${app_name_upper}_DOMAIN_NAME\""
280
+    echo '    else'
281
+    echo "        interactive_site_details \"${app_name}\" \"${app_name_upper}_DOMAIN_NAME\" \"${app_name}_CODE\""
282
+    echo '    fi'
283
+else
284
+    echo "    echo -n ''"
285
+fi
234 286
 echo '    APP_INSTALLED=1'
235 287
 echo '}'
236 288
 echo ''
@@ -311,8 +363,13 @@ echo "        ${app_name_upper}_DOMAIN_NAME=\$(get_completion_param \"${app_name
311 363
 echo '    fi'
312 364
 echo ''
313 365
 echo '    # update to the next commit'
314
-echo "    set_repo_commit /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs \"${app_name} commit\" \"\$${app_name_upper}_COMMIT\" \$${app_name_upper}_REPO"
315
-echo "    chown -R www-data:www-data /var/www/\${${app_name_upper}_DOMAIN_NAME}/htdocs"
366
+if [ ! $app_dir ]; then
367
+    echo "    set_repo_commit /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs \"${app_name} commit\" \"\$${app_name_upper}_COMMIT\" \$${app_name_upper}_REPO"
368
+    echo "    chown -R www-data:www-data /var/www/\${${app_name_upper}_DOMAIN_NAME}/htdocs"
369
+else
370
+    echo "    set_repo_commit ${app_dir} \"${app_name} commit\" \"\$${app_name_upper}_COMMIT\" \$${app_name_upper}_REPO"
371
+    echo "    chown -R ${app_name}:${app_name} ${app_dir}"
372
+fi
316 373
 echo '}'
317 374
 echo ''
318 375
 echo "function backup_local_${app_name} {"
@@ -321,7 +378,11 @@ echo "    if grep -q \"${app_name} domain\" \$COMPLETION_FILE; then"
321 378
 echo "        ${app_name_upper}_DOMAIN_NAME=\$(get_completion_param \"${app_name} domain\")"
322 379
 echo '    fi'
323 380
 echo ''
324
-echo "    source_directory=/var/www/\${${app_name_upper}_DOMAIN_NAME}/htdocs"
381
+if [ ! $app_dir ]; then
382
+    echo "    source_directory=/var/www/\${${app_name_upper}_DOMAIN_NAME}/htdocs"
383
+else
384
+    echo "    source_directory=${app_dir}"
385
+fi
325 386
 echo ''
326 387
 echo "    suspend_site \${${app_name_upper}_DOMAIN_NAME}"
327 388
 echo ''
@@ -347,7 +408,11 @@ echo '    fi'
347 408
 echo "    ${app_name_upper}_DOMAIN_NAME=\$(get_completion_param \"${app_name} domain\")"
348 409
 echo "    if [ \$${app_name_upper}_DOMAIN_NAME ]; then"
349 410
 echo "        temp_restore_dir=/root/temp${app_name}"
350
-echo "        ${app_name}_dir=/var/www/\${${app_name_upper}_DOMAIN_NAME}/htdocs"
411
+if [ ! $app_dir ]; then
412
+    echo "        ${app_name}_dir=/var/www/\${${app_name_upper}_DOMAIN_NAME}/htdocs"
413
+else
414
+    echo "        ${app_name}_dir=${app_dir}"
415
+fi
351 416
 echo ''
352 417
 if [[ "$database_type" == "mariadb" || "$database_type" == "mysql" ]]; then
353 418
     echo "        ${app_name}_create_database"
@@ -391,7 +456,11 @@ echo "    if grep -q \"${app_name} domain\" \$COMPLETION_FILE; then"
391 456
 echo "        ${app_name_upper}_DOMAIN_NAME=\$(get_completion_param \"${app_name} domain\")"
392 457
 echo '    fi'
393 458
 echo ''
394
-echo "    source_directory=/var/www/\${${app_name_upper}_DOMAIN_NAME}/htdocs"
459
+if [ ! $app_dir ]; then
460
+    echo "    source_directory=/var/www/\${${app_name_upper}_DOMAIN_NAME}/htdocs"
461
+else
462
+    echo "    source_directory=${app_dir}"
463
+fi
395 464
 echo ''
396 465
 echo "    suspend_site \${${app_name_upper}_DOMAIN_NAME}"
397 466
 echo ''
@@ -417,7 +486,11 @@ echo '    fi'
417 486
 echo "    ${app_name_upper}_DOMAIN_NAME=\$(get_completion_param \"${app_name} domain\")"
418 487
 echo "    if [ \$${app_name_upper}_DOMAIN_NAME ]; then"
419 488
 echo "        temp_restore_dir=/root/temp${app_name}"
420
-echo "        ${app_name}_dir=/var/www/\${${app_name_upper}_DOMAIN_NAME}/htdocs"
489
+if [ ! $app_dir ]; then
490
+    echo "        ${app_name}_dir=/var/www/\${${app_name_upper}_DOMAIN_NAME}/htdocs"
491
+else
492
+    echo "        ${app_name}_dir=${app_dir}"
493
+fi
421 494
 echo ''
422 495
 if [[ "$database_type" == "mariadb" || "$database_type" == "mysql" ]]; then
423 496
     echo "        ${app_name}_create_database"
@@ -463,6 +536,15 @@ fi
463 536
 echo "    nginx_dissite \$${app_name_upper}_DOMAIN_NAME"
464 537
 echo "    remove_certs \$${app_name_upper}_DOMAIN_NAME"
465 538
 echo ''
539
+if [ $app_daemon ]; then
540
+    echo "    if [ -f /etc/systemd/system/${app_name}.service ]; then"
541
+    echo "        systemctl stop ${app_name}"
542
+    echo "        systemctl disable ${app_name}"
543
+    echo "        rm /etc/systemd/system/${app_name}.service"
544
+    echo '    fi'
545
+    echo "    userdel -r ${app_name}"
546
+fi
547
+echo ''
466 548
 echo "    if [ -d /var/www/\$${app_name_upper}_DOMAIN_NAME ]; then"
467 549
 echo "        rm -rf /var/www/\$${app_name_upper}_DOMAIN_NAME"
468 550
 echo '    fi'
@@ -482,10 +564,10 @@ echo '    fi'
482 564
 echo "    remove_app ${app_name}"
483 565
 echo "    remove_completion_param install_${app_name}"
484 566
 echo "    sed -i '/${app_name}/d' \$COMPLETION_FILE"
485
-echo ''
486
-echo "    if grep -q '${app_name}-firewall' /etc/crontab; then"
487
-echo "        sed -i '/${app_name}-firewall/d' /etc/crontab"
488
-echo '    fi'
567
+if [ $app_port ]; then
568
+    echo ''
569
+    echo "    firewall_remove ${app_port} tcp"
570
+fi
489 571
 echo ''
490 572
 echo "    remove_ddns_domain \$${app_name_upper}_DOMAIN_NAME"
491 573
 echo '}'
@@ -515,27 +597,44 @@ echo '    fi'
515 597
 echo "    if [ ! -d /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs ]; then"
516 598
 echo "        if [ -d /repos/${app_name} ]; then"
517 599
 echo "            mkdir /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
518
-echo "            cp -r -p /repos/${app_name}/. /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
519
-echo "            cd /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
600
+if [ ! $app_dir ]; then
601
+    echo "            cp -r -p /repos/${app_name}/. /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
602
+    echo "            cd /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
603
+else
604
+    echo "            cp -r -p /repos/${app_name}/. ${app_dir}"
605
+    echo "            cd ${app_dir}"
606
+fi
520 607
 echo '            git pull'
521 608
 echo '        else'
522
-echo "            git_clone \$${app_name_upper}_REPO /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
609
+if [ ! $app_dir ]; then
610
+    echo "            git_clone \$${app_name_upper}_REPO /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
611
+else
612
+    echo "            git_clone \$${app_name_upper}_REPO ${app_dir}"
613
+fi
523 614
 echo '        fi'
524 615
 echo ''
525
-echo "        if [ ! -d /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs ]; then"
616
+if [ ! $app_dir ]; then
617
+    echo "        if [ ! -d /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs ]; then"
618
+else
619
+    echo "        if [ ! -d ${app_dir} ]; then"
620
+fi
526 621
 echo "            echo \$'Unable to clone ${app_name} repo'"
527 622
 echo '            exit 87525'
528 623
 echo '        fi'
529 624
 echo '    fi'
530 625
 echo ''
531
-echo "    cd /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
626
+if [ ! $app_dir ]; then
627
+    echo "    cd /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
628
+else
629
+    echo "    cd ${app_dir}"
630
+fi
532 631
 echo "    git checkout \$${app_name_upper}_COMMIT -b \$${app_name_upper}_COMMIT"
533 632
 echo "    set_completion_param \"${app_name} commit\" \"\$${app_name_upper}_COMMIT\""
534 633
 echo ''
535 634
 echo "    chmod g+w /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
536 635
 echo "    chown -R www-data:www-data /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs"
537 636
 
538
-if [[ "$database_type" == "mariadb" || "$database_type" == "mysql" ]]; then
637
+if [[ "$database_type" == "mariadb" || "$database_type" == "mysql" || "$database_type" == "postgres"*  ]]; then
539 638
     echo ''
540 639
     echo "    ${app_name}_create_database"
541 640
 fi
@@ -545,53 +644,62 @@ echo ''
545 644
 echo "    ${app_name_upper}_ONION_HOSTNAME=\$(add_onion_service ${app_name} 80 \${${app_name_upper}_ONION_PORT})"
546 645
 echo ''
547 646
 echo "    ${app_name}_nginx_site=/etc/nginx/sites-available/\$${app_name_upper}_DOMAIN_NAME"
548
-echo '    if [[ $ONION_ONLY == "no" ]]; then'
549
-if [[ "$app_php" == 'yes' ]]; then
550
-    echo "        nginx_http_redirect \$${app_name_upper}_DOMAIN_NAME \"index index.php\""
551
-else
552
-    echo "        nginx_http_redirect \$${app_name_upper}_DOMAIN_NAME \"index index.html\""
553
-fi
554
-echo "        echo 'server {' >> \$${app_name}_nginx_site"
555
-echo "        echo '  listen 443 ssl;' >> \$${app_name}_nginx_site"
556
-echo "        echo '  listen [::]:443 ssl;' >> \$${app_name}_nginx_site"
557
-echo "        echo \"  server_name \$${app_name_upper}_DOMAIN_NAME;\" >> \$${app_name}_nginx_site"
558
-echo "        echo '' >> \$${app_name}_nginx_site"
559
-echo "        nginx_compress \$${app_name_upper}_DOMAIN_NAME"
560
-echo "        echo '' >> \$${app_name}_nginx_site"
561
-echo "        echo '  # Security' >> \$${app_name}_nginx_site"
562
-echo "        nginx_ssl \$${app_name_upper}_DOMAIN_NAME"
563
-echo ''
564
-echo "        nginx_disable_sniffing \$${app_name_upper}_DOMAIN_NAME"
565
-echo ''
566
-echo "        echo '  add_header Strict-Transport-Security max-age=15768000;' >> \$${app_name}_nginx_site"
567
-echo "        echo '' >> \$${app_name}_nginx_site"
568
-echo "        echo '  # Logs' >> \$${app_name}_nginx_site"
569
-echo "        echo '  access_log /dev/null;' >> \$${app_name}_nginx_site"
570
-echo "        echo '  error_log /dev/null;' >> \$${app_name}_nginx_site"
571
-echo "        echo '' >> \$${app_name}_nginx_site"
572
-echo "        echo '  # Root' >> \$${app_name}_nginx_site"
573
-echo "        echo \"  root /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs;\" >> \$${app_name}_nginx_site"
574
-echo "        echo '' >> \$${app_name}_nginx_site"
575
-if [[ "$app_php" == 'yes' ]]; then
576
-    echo "        echo '  index index.php;' >> \$${app_name}_nginx_site"
577
-    echo "        echo '  location ~ \.php {' >> \$${app_name}_nginx_site"
578
-    echo "        echo '    include snippets/fastcgi-php.conf;' >> \$${app_name}_nginx_site"
579
-    echo "        echo '    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;' >> \$${app_name}_nginx_site"
580
-    echo "        echo '    fastcgi_read_timeout 30;' >> \$${app_name}_nginx_site"
581
-    echo "        echo '  }' >> \$${app_name}_nginx_site"
647
+
648
+if [ $app_onion_only ]; then
649
+    echo '    if [[ $ONION_ONLY == "no" ]]; then'
650
+    if [[ "$app_php" == 'yes' ]]; then
651
+        echo "        nginx_http_redirect \$${app_name_upper}_DOMAIN_NAME \"index index.php\""
652
+    else
653
+        echo "        nginx_http_redirect \$${app_name_upper}_DOMAIN_NAME \"index index.html\""
654
+    fi
655
+    echo "        echo 'server {' >> \$${app_name}_nginx_site"
656
+    echo "        echo '  listen 443 ssl;' >> \$${app_name}_nginx_site"
657
+    echo "        echo '  listen [::]:443 ssl;' >> \$${app_name}_nginx_site"
658
+    echo "        echo \"  server_name \$${app_name_upper}_DOMAIN_NAME;\" >> \$${app_name}_nginx_site"
659
+    echo "        echo '' >> \$${app_name}_nginx_site"
660
+    echo "        nginx_compress \$${app_name_upper}_DOMAIN_NAME"
661
+    echo "        echo '' >> \$${app_name}_nginx_site"
662
+    echo "        echo '  # Security' >> \$${app_name}_nginx_site"
663
+    echo "        nginx_ssl \$${app_name_upper}_DOMAIN_NAME"
664
+    echo ''
665
+    echo "        nginx_disable_sniffing \$${app_name_upper}_DOMAIN_NAME"
666
+    echo ''
667
+    echo "        echo '  add_header Strict-Transport-Security max-age=15768000;' >> \$${app_name}_nginx_site"
668
+    echo "        echo '' >> \$${app_name}_nginx_site"
669
+    echo "        echo '  # Logs' >> \$${app_name}_nginx_site"
670
+    echo "        echo '  access_log /dev/null;' >> \$${app_name}_nginx_site"
671
+    echo "        echo '  error_log /dev/null;' >> \$${app_name}_nginx_site"
582 672
     echo "        echo '' >> \$${app_name}_nginx_site"
673
+    echo "        echo '  # Root' >> \$${app_name}_nginx_site"
674
+    echo "        echo \"  root /var/www/\$${app_name_upper}_DOMAIN_NAME/htdocs;\" >> \$${app_name}_nginx_site"
675
+    echo "        echo '' >> \$${app_name}_nginx_site"
676
+    if [[ "$app_php" == 'yes' ]]; then
677
+        echo "        echo '  index index.php;' >> \$${app_name}_nginx_site"
678
+        echo "        echo '  location ~ \.php {' >> \$${app_name}_nginx_site"
679
+        echo "        echo '    include snippets/fastcgi-php.conf;' >> \$${app_name}_nginx_site"
680
+        echo "        echo '    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;' >> \$${app_name}_nginx_site"
681
+        echo "        echo '    fastcgi_read_timeout 30;' >> \$${app_name}_nginx_site"
682
+        echo "        echo '  }' >> \$${app_name}_nginx_site"
683
+        echo "        echo '' >> \$${app_name}_nginx_site"
684
+    else
685
+        echo "        echo '  index index.html;' >> \$${app_name}_nginx_site"
686
+    fi
687
+    echo "        echo '  # Location' >> \$${app_name}_nginx_site"
688
+    echo "        echo '  location / {' >> \$${app_name}_nginx_site"
689
+    echo "        nginx_limits \$${app_name_upper}_DOMAIN_NAME '15m'"
690
+    if [ ! $app_daemon ]; then
691
+        echo "        echo '    try_files \$uri \$uri/ /index.html;' >> \$${app_name}_nginx_site"
692
+    else
693
+        echo "        echo \"    proxy_pass http://localhost:\$${app_name_upper}_PORT_INTERNAL;\" >> \$${app_name}_nginx_site"
694
+    fi
695
+    echo "        echo '  }' >> \$${app_name}_nginx_site"
696
+    echo "        echo '}' >> \$${app_name}_nginx_site"
697
+    echo '    else'
698
+    echo "        echo -n '' > \$${app_name}_nginx_site"
699
+    echo '    fi'
583 700
 else
584
-    echo "        echo '  index index.html;' >> \$${app_name}_nginx_site"
701
+    echo "    echo -n '' > \$${app_name}_nginx_site"
585 702
 fi
586
-echo "        echo '  # Location' >> \$${app_name}_nginx_site"
587
-echo "        echo '  location / {' >> \$${app_name}_nginx_site"
588
-echo "        nginx_limits \$${app_name_upper}_DOMAIN_NAME '15m'"
589
-echo "        echo '    try_files \$uri \$uri/ @${app_name};' >> \$${app_name}_nginx_site"
590
-echo "        echo '  }' >> \$${app_name}_nginx_site"
591
-echo "        echo '}' >> \$${app_name}_nginx_site"
592
-echo '    else'
593
-echo "        echo -n '' > \$${app_name}_nginx_site"
594
-echo '    fi'
595 703
 echo "    echo 'server {' >> \$${app_name}_nginx_site"
596 704
 echo "    echo \"    listen 127.0.0.1:\$${app_name_upper}_ONION_PORT default_server;\" >> \$${app_name}_nginx_site"
597 705
 echo "    echo \"    server_name \$${app_name_upper}_ONION_HOSTNAME;\" >> \$${app_name}_nginx_site"
@@ -621,13 +729,47 @@ fi
621 729
 echo "    echo '  # Location' >> \$${app_name}_nginx_site"
622 730
 echo "    echo '  location / {' >> \$${app_name}_nginx_site"
623 731
 echo "    nginx_limits \$${app_name_upper}_DOMAIN_NAME '15m'"
624
-echo "    echo '    try_files \$uri \$uri/ @${app_name};' >> \$${app_name}_nginx_site"
732
+if [ ! $app_daemon ]; then
733
+    echo "    echo '    try_files \$uri \$uri/ index.html;' >> \$${app_name}_nginx_site"
734
+else
735
+    echo "    echo \"    proxy_pass http://localhost:\$${app_name_upper}_PORT_INTERNAL;\" >> \$${app_name}_nginx_site"
736
+fi
625 737
 echo "    echo '  }' >> \$${app_name}_nginx_site"
626 738
 echo "    echo '}' >> \$${app_name}_nginx_site"
627 739
 if [[ "$app_php" == 'yes' ]]; then
628 740
     echo ''
629 741
     echo '    configure_php'
630 742
 fi
743
+if [ $app_daemon ]; then
744
+    echo ''
745
+    echo "    useradd -d TODO_PATH_TO_INSTALL -s /bin/false ${app_name}"
746
+    echo ''
747
+    echo "    echo '[Unit]' > /etc/systemd/system/${app_name}.service"
748
+    echo "    echo 'Description=${app_name}' >> /etc/systemd/system/${app_name}.service"
749
+    echo "    echo 'After=syslog.target' >> /etc/systemd/system/${app_name}.service"
750
+    echo "    echo 'After=network.target' >> /etc/systemd/system/${app_name}.service"
751
+    echo "    echo '' >> /etc/systemd/system/${app_name}.service"
752
+    echo "    echo '[Service]' >> /etc/systemd/system/${app_name}.service"
753
+    echo "    echo 'Type=simple' >> /etc/systemd/system/${app_name}.service"
754
+    echo "    echo 'User=${app_name}' >> /etc/systemd/system/${app_name}.service"
755
+    echo "    echo 'Group=${app_name}' >> /etc/systemd/system/${app_name}.service"
756
+    if [ ! $app_dir ]; then
757
+        echo "    echo 'WorkingDirectory=TODO' >> /etc/systemd/system/${app_name}.service"
758
+    else
759
+        echo "    echo 'WorkingDirectory=${app_dir}' >> /etc/systemd/system/${app_name}.service"
760
+    fi
761
+    echo "    echo 'ExecStart=TODO' >> /etc/systemd/system/${app_name}.service"
762
+    echo "    echo 'Restart=always' >> /etc/systemd/system/${app_name}.service"
763
+    echo "    echo 'Environment=\"USER=${app_name}\"' >> /etc/systemd/system/${app_name}.service"
764
+    echo "    echo '' >> /etc/systemd/system/${app_name}.service"
765
+    echo "    echo '[Install]' >> /etc/systemd/system/${app_name}.service"
766
+    echo "    echo 'WantedBy=multi-user.target' >> /etc/systemd/system/${app_name}.service"
767
+    echo "    systemctl enable ${app_name}"
768
+    if [ $app_dir ]; then
769
+        echo "    chown -R ${app_name}:${app_name} ${app_dir}"
770
+    fi
771
+    echo "    systemctl start ${app_name}"
772
+fi
631 773
 echo ''
632 774
 echo "    create_site_certificate \$${app_name_upper}_DOMAIN_NAME 'yes'"
633 775
 echo ''
@@ -643,6 +785,10 @@ echo '    systemctl restart nginx'
643 785
 echo ''
644 786
 echo "    \${PROJECT_NAME}-pass -u \$MY_USERNAME -a ${app_name} -p \"\$${app_name_upper}_ADMIN_PASSWORD\""
645 787
 echo "    set_completion_param \"${app_name} domain\" \"\$${app_name_upper}_DOMAIN_NAME\""
788
+if [ $app_port ]; then
789
+    echo ''
790
+    echo "    firewall_add ${app_name} ${app_port} tcp"
791
+fi
646 792
 echo ''
647 793
 echo '    APP_INSTALLED=1'
648 794
 echo '}'

+ 65
- 231
website/EN/devguide.html 查看文件

@@ -3,7 +3,7 @@
3 3
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4 4
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
5 5
 <head>
6
-<!-- 2017-12-20 Wed 12:42 -->
6
+<!-- 2018-02-07 Wed 10:46 -->
7 7
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
8 8
 <meta name="viewport" content="width=device-width, initial-scale=1" />
9 9
 <title>&lrm;</title>
@@ -246,297 +246,131 @@ for the JavaScript code in this tag.
246 246
 
247 247
 <center><h1>Developers Guide</h1></center>
248 248
 
249
-<div id="outline-container-org6818d03" class="outline-2">
250
-<h2 id="org6818d03">Introduction</h2>
251
-<div class="outline-text-2" id="text-org6818d03">
249
+<div id="outline-container-orgcb772bb" class="outline-2">
250
+<h2 id="orgcb772bb">Introduction</h2>
251
+<div class="outline-text-2" id="text-orgcb772bb">
252 252
 <p>
253
-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. You might also want to consult the <a href="./codeofconduct.html">Code of Conduct</a>.
253
+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. You might also want to consult the <a href="./codeofconduct.html">Code of Conduct</a>, and there is a Matrix room at <b>#fbone:matrix.freedombone.net</b>
254 254
 </p>
255 255
 </div>
256 256
 </div>
257
-<div id="outline-container-org080672c" class="outline-2">
258
-<h2 id="org080672c">Adding extra apps</h2>
259
-<div class="outline-text-2" id="text-org080672c">
257
+<div id="outline-container-org8fd5474" class="outline-2">
258
+<h2 id="org8fd5474">Adding extra apps</h2>
259
+<div class="outline-text-2" id="text-org8fd5474">
260 260
 <p>
261 261
 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.
262 262
 </p>
263 263
 
264 264
 <p>
265
-On an installed system the app scripts go into the directory:
265
+There's a command which you can use to generate scripts for new apps. Some examples are as follows:
266
+</p>
267
+
268
+<p>
269
+To create a script for a generic PHP plus MySql/MariaDB web app:
266 270
 </p>
267 271
 
268 272
 <div class="org-src-container">
269
-<pre class="src src-bash">/usr/share/freedombone/apps
273
+<pre class="src src-bash">freedombone-template --app [name] -e [email] -r [repo url] <span class="org-sh-escaped-newline">\</span>
274
+                     -c [commit] --php yes -d mariadb &gt; <span class="org-sh-escaped-newline">\</span>
275
+                     src/freedombone-app-myappname
270 276
 </pre>
271 277
 </div>
272 278
 
273 279
 <p>
274
-and within the project repo they appear within the <i>src</i> directory. Your new app script should have the name:
280
+For a Nodejs app with MySql/MariaDB database:
275 281
 </p>
276 282
 
277 283
 <div class="org-src-container">
278
-<pre class="src src-bash">freedombone-app-[myappname]
284
+<pre class="src src-bash">freedombone-template --app [name] -e [email] -r [repo url] <span class="org-sh-escaped-newline">\</span>
285
+                     -c [commit] --node yes -d mariadb <span class="org-sh-escaped-newline">\</span>
286
+                     --dir /etc/myappname --daemon yes &gt; <span class="org-sh-escaped-newline">\</span>
287
+                     src/freedombone-app-myappname
279 288
 </pre>
280 289
 </div>
281 290
 
282 291
 <p>
283
-The <i>myappname</i> value should not contain any spaces and will appear in the list of available apps.
292
+For a Python app with Postgresql database:
284 293
 </p>
285 294
 
295
+<div class="org-src-container">
296
+<pre class="src src-bash">freedombone-template --app [name] -e [email] -r [repo url] <span class="org-sh-escaped-newline">\</span>
297
+                     -c [commit] -d postgresql <span class="org-sh-escaped-newline">\</span>
298
+                     --dir /etc/myappname --daemon yes &gt; <span class="org-sh-escaped-newline">\</span>
299
+                     src/freedombone-app-myappname
300
+</pre>
301
+</div>
302
+
286 303
 <p>
287
-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.
304
+For a Python app without any database, communicating between the daemon and the web server on port 1234:
288 305
 </p>
289 306
 
290 307
 <div class="org-src-container">
291
-<pre class="src src-bash"><span class="org-comment-delimiter">#</span><span class="org-comment">!/bin/</span><span class="org-keyword">bash</span>
292
-<span class="org-comment-delimiter"># </span><span class="org-comment">Copyright (C) Year YourName &lt;YourEmail&gt;</span>
293
-<span class="org-comment-delimiter">#</span>
294
-<span class="org-comment-delimiter"># </span><span class="org-comment">This program is free software: you can redistribute it</span>
295
-<span class="org-comment-delimiter"># </span><span class="org-comment">and/or modify it under the terms of the GNU Affero General</span>
296
-<span class="org-comment-delimiter"># </span><span class="org-comment">Public License as published by the Free Software Foundation,</span>
297
-<span class="org-comment-delimiter"># </span><span class="org-comment">either version 3 of the License, or (at your option) any</span>
298
-<span class="org-comment-delimiter"># </span><span class="org-comment">later version.</span>
299
-<span class="org-comment-delimiter">#</span>
300
-<span class="org-comment-delimiter"># </span><span class="org-comment">This program is distributed in the hope that it will be useful,</span>
301
-<span class="org-comment-delimiter"># </span><span class="org-comment">but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
302
-<span class="org-comment-delimiter"># </span><span class="org-comment">MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
303
-<span class="org-comment-delimiter"># </span><span class="org-comment">GNU Affero General Public License for more details.</span>
304
-
305
-<span class="org-comment-delimiter"># </span><span class="org-comment">'full' includes your app in the full installation and you</span>
306
-<span class="org-comment-delimiter"># </span><span class="org-comment">can also add other variants, separated by spaces. The</span>
307
-<span class="org-comment-delimiter"># </span><span class="org-comment">available variants will be detected automatically from the</span>
308
-<span class="org-comment-delimiter"># </span><span class="org-comment">app scripts. In most cases don't change this.</span>
309
-<span class="org-variable-name">VARIANTS</span>=<span class="org-string">'full'</span>
310
-
311
-<span class="org-comment-delimiter"># </span><span class="org-comment">If you want this to appear on the control panel About screen</span>
312
-<span class="org-variable-name">SHOW_ON_ABOUT</span>=1
313
-
314
-<span class="org-comment-delimiter"># </span><span class="org-comment">If you want this app to be in the default installation,</span>
315
-<span class="org-comment-delimiter"># </span><span class="org-comment">otherwise it will be available but not selected by default</span>
316
-<span class="org-variable-name">IN_DEFAULT_INSTALL</span>=1
317
-
318
-<span class="org-variable-name">SOME_IMPORTANT_CONFIG_VARIABLE</span>=<span class="org-string">'some important value'</span>
319
-<span class="org-variable-name">ANOTHER_IMPORTANT_CONFIG_VARIABLE</span>=<span class="org-string">'foo'</span>
320
-<span class="org-variable-name">MY_FUNKY_AVATAR</span>=https://some-domain-or-other/fro.png
321
-<span class="org-variable-name">MYAPPNAME_ONION_PORT</span>=[port number]
322
-<span class="org-variable-name">MYAPPNAME_DB_PASSWORD</span>=
323
-
324
-<span class="org-comment-delimiter"># </span><span class="org-comment">A directory where the data for this app exists</span>
325
-<span class="org-variable-name">MYAPP_DATA_DIR</span>=/var/lib/somedirectory
326
-
327
-<span class="org-comment-delimiter"># </span><span class="org-comment">List of configuration variables used by the app</span>
328
-<span class="org-variable-name">myappname_variables</span>=(ONION_ONLY
329
-                     MY_USERNAME
330
-                     SOME_IMPORTANT_CONFIG_VARIABLE
331
-                     ANOTHER_IMPORTANT_CONFIG_VARIABLE
332
-                     MY_FUNKY_AVATAR
333
-                     MYAPPNAME_ONION_PORT
334
-                     MYAPPNAME_DB_PASSWORD)
335
-
336
-<span class="org-keyword">function</span> <span class="org-function-name">logging_on_myappname</span> {
337
-    <span class="org-builtin">echo</span> -n <span class="org-string">''</span>
338
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Commands to turn on logging go here</span>
339
-}
340
-
341
-<span class="org-keyword">function</span> <span class="org-function-name">logging_off_myappname</span> {
342
-    <span class="org-builtin">echo</span> -n <span class="org-string">''</span>
343
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Commands to turn off logging go here</span>
344
-}
345
-
346
-<span class="org-keyword">function</span> <span class="org-function-name">change_password_myappname</span> {
347
-    <span class="org-variable-name">PASSWORD_USERNAME</span>=<span class="org-string">"$1"</span>
348
-    <span class="org-variable-name">PASSWORD_NEW</span>=<span class="org-string">"$2"</span>
349
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Do something to change the password</span>
350
-}
351
-
352
-<span class="org-keyword">function</span> <span class="org-function-name">reconfigure_myappname</span> {
353
-    <span class="org-builtin">echo</span> -n <span class="org-string">''</span>
354
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Do something to delete existing keys/identity and</span>
355
-    <span class="org-comment-delimiter"># </span><span class="org-comment">generate new ones</span>
356
-}
357
-
358
-<span class="org-keyword">function</span> <span class="org-function-name">upgrade_myappname</span> {
359
-    <span class="org-builtin">echo</span> -n <span class="org-string">''</span>
360
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Do something to upgrade this app.</span>
361
-    <span class="org-comment-delimiter"># </span><span class="org-comment">If it's a debian package then it will be maintained by the</span>
362
-    <span class="org-comment-delimiter"># </span><span class="org-comment">operating system and you don't need anything here</span>
363
-}
364
-
365
-<span class="org-keyword">function</span> <span class="org-function-name">backup_local_myappname</span> {
366
-    <span class="org-comment-delimiter"># </span><span class="org-comment">If your app has a MariaDB/MySQL database</span>
367
-    backup_database_to_usb myappname
368
-
369
-    <span class="org-comment-delimiter"># </span><span class="org-comment">To backup a directory</span>
370
-    backup_directory_to_usb $<span class="org-variable-name">MYAPP_DATA_DIR</span> myappname
371
-
372
-    <span class="org-comment-delimiter"># </span><span class="org-comment">if you need to backup data within individual user</span>
373
-    <span class="org-comment-delimiter"># </span><span class="org-comment">home directories</span>
374
-    <span class="org-keyword">for</span> d<span class="org-keyword"> in</span> /home/*/ ; <span class="org-keyword">do</span>
375
-        <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>)
376
-        <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>
377
-            <span class="org-builtin">echo</span> $<span class="org-string">"Backing up myappname config for $USERNAME"</span>
378
-            <span class="org-keyword">if</span> [ -d /home/$<span class="org-variable-name">USERNAME</span>/.config/myappname ]; <span class="org-keyword">then</span>
379
-                backup_directory_to_usb <span class="org-sh-escaped-newline">\</span>
380
-                    /home/$<span class="org-variable-name">USERNAME</span>/.config/myappname <span class="org-sh-escaped-newline">\</span>
381
-                    myappname_users/$<span class="org-variable-name">USERNAME</span>
382
-            <span class="org-keyword">fi</span>
383
-        <span class="org-keyword">fi</span>
384
-    <span class="org-keyword">done</span>
385
-}
386
-
387
-<span class="org-keyword">function</span> <span class="org-function-name">restore_local_myappname</span> {
388
-    <span class="org-variable-name">temp_restore_dir</span>=/root/tempmyappname
389
-
390
-    <span class="org-comment-delimiter"># </span><span class="org-comment">If your app has a MariaDB/MySQL database</span>
391
-    restore_database myappname
392
-
393
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Restore some data from a directory</span>
394
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Note that we don't restore directly but to a temporary</span>
395
-    <span class="org-comment-delimiter"># </span><span class="org-comment">directory and then copy the files. This ensures that if</span>
396
-    <span class="org-comment-delimiter"># </span><span class="org-comment">there is a restore failure you don't end up with</span>
397
-    <span class="org-comment-delimiter"># </span><span class="org-comment">half-copied or corrupted files</span>
398
-    restore_directory_from_usb $<span class="org-variable-name">MYAPP_DATA_DIR</span> myappname
399
-    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>
400
-    rm -rf $<span class="org-variable-name">temp_restore_dir</span>
401
-
402
-    <span class="org-comment-delimiter"># </span><span class="org-comment">If you need to restore a configuration directory for each user</span>
403
-    <span class="org-keyword">if</span> [ -d $<span class="org-variable-name">USB_MOUNT</span>/backup/myappname_users ]; <span class="org-keyword">then</span>
404
-        <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>
405
-            <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>)
406
-            <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>
407
-                <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>
408
-                    ${<span class="org-variable-name">PROJECT_NAME</span>}-adduser $<span class="org-variable-name">USERNAME</span>
409
-                <span class="org-keyword">fi</span>
410
-                <span class="org-builtin">echo</span> $<span class="org-string">"Restoring Vim config for $USERNAME"</span>
411
-                function_check restore_directory_from_usb
412
-                restore_directory_from_usb $<span class="org-variable-name">temp_restore_dir</span> <span class="org-sh-escaped-newline">\</span>
413
-                                           myappname_users/$<span class="org-variable-name">USERNAME</span>
414
-                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>
415
-                      /home/$<span class="org-variable-name">USERNAME</span>/
416
-                <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>
417
-                    rm -rf $<span class="org-variable-name">temp_restore_dir</span>
418
-                    set_user_permissions
419
-                    backup_unmount_drive
420
-                    <span class="org-keyword">exit</span> 664
421
-                <span class="org-keyword">fi</span>
422
-                rm -rf $<span class="org-variable-name">temp_restore_dir</span>
423
-            <span class="org-keyword">fi</span>
424
-        <span class="org-keyword">done</span>
425
-    <span class="org-keyword">fi</span>
426
-}
427
-
428
-<span class="org-keyword">function</span> <span class="org-function-name">backup_remote_myappname</span> {
429
-    <span class="org-comment-delimiter"># </span><span class="org-comment">this should be the same as backup_local_myappname,</span>
430
-    <span class="org-comment-delimiter"># </span><span class="org-comment">but call the backup functions backup_directory_to_friend</span>
431
-    <span class="org-comment-delimiter"># </span><span class="org-comment">and backup_database_to_friend</span>
432
-}
433
-
434
-<span class="org-keyword">function</span> <span class="org-function-name">restore_remote_vim</span> {
435
-    <span class="org-comment-delimiter"># </span><span class="org-comment">this should be the same as restore_local_myappname,</span>
436
-    <span class="org-comment-delimiter"># </span><span class="org-comment">but call the restore function restore_directory_from_friend</span>
437
-    <span class="org-comment-delimiter"># </span><span class="org-comment">and restore_database_from_friend</span>
438
-}
439
-
440
-<span class="org-keyword">function</span> <span class="org-function-name">remove_myappname</span> {
441
-    <span class="org-comment-delimiter"># </span><span class="org-comment">if it's a debian package then:</span>
442
-    apt-get -y remove --purge [my-app-package-name]
443
-
444
-    <span class="org-comment-delimiter"># </span><span class="org-comment">If your app has a MariaDB/MySQL database</span>
445
-    drop_database myappname
446
-
447
-    <span class="org-comment-delimiter"># </span><span class="org-comment">If your app uses an onion address</span>
448
-    remove_onion_service myappname ${<span class="org-variable-name">MYAPPNAME_ONION_PORT</span>}
449
-}
450
-
451
-<span class="org-keyword">function</span> <span class="org-function-name">install_myappname</span> {
452
-    <span class="org-comment-delimiter"># </span><span class="org-comment">if it's a debian package then:</span>
453
-    apt-get -y install [my-app-package-name]
454
-
455
-    <span class="org-comment-delimiter"># </span><span class="org-comment">If you need to create a MariaDB/MySQL database for the app</span>
456
-    <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>
457
-    create_database myappname <span class="org-string">"$MYAPPNAME_DB_PASSWORD"</span> $<span class="org-variable-name">MY_USERNAME</span>
458
-
459
-    <span class="org-comment-delimiter"># </span><span class="org-comment">If you need to create an onion address for the app</span>
460
-    <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>
461
-                               80 ${<span class="org-variable-name">MYAPPNAME_ONION_PORT</span>})
308
+<pre class="src src-bash">freedombone-template --app [name] -e [email] -r [repo url] <span class="org-sh-escaped-newline">\</span>
309
+                     -c [commit] --dir /etc/myappname <span class="org-sh-escaped-newline">\</span>
310
+                     --daemon yes --portinternal 1234 &gt; <span class="org-sh-escaped-newline">\</span>
311
+                     src/freedombone-app-myappname
312
+</pre>
313
+</div>
462 314
 
463
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Do any other configuration</span>
464
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Here you might use $ONION_ONLY or</span>
465
-    <span class="org-comment-delimiter"># </span><span class="org-comment">$SOME_IMPORTANT_CONFIG_VARIABLE</span>
315
+<p>
316
+For an app without any database which communicates directly on a particular port through the firewall:
317
+</p>
466 318
 
467
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Mark the app as having installed successfully</span>
468
-    <span class="org-comment-delimiter"># </span><span class="org-comment">If this variable isn't set then it will be assumed that</span>
469
-    <span class="org-comment-delimiter"># </span><span class="org-comment">the install has failed</span>
470
-    <span class="org-variable-name">APP_INSTALLED</span>=1
471
-}
319
+<div class="org-src-container">
320
+<pre class="src src-bash">freedombone-template --app [name] -e [email] -r [repo url] <span class="org-sh-escaped-newline">\</span>
321
+                     -c [commit] --dir /etc/myappname <span class="org-sh-escaped-newline">\</span>
322
+                     --daemon yes --port 5000 &gt; <span class="org-sh-escaped-newline">\</span>
323
+                     src/freedombone-app-myappname
324
+</pre>
325
+</div>
472 326
 
473
-<span class="org-keyword">function</span> <span class="org-function-name">install_interactive_myappname</span> {
474
-    <span class="org-comment-delimiter"># </span><span class="org-comment">Interactively obtain some values using dialog, such as</span>
475
-    <span class="org-comment-delimiter"># </span><span class="org-comment">domain names. An avatar changing example is:</span>
476
-    <span class="org-variable-name">data</span>=$(<span class="org-sh-quoted-exec">tempfile</span> 2&gt;/dev/null)
477
-    <span class="org-keyword">trap</span> <span class="org-string">"rm -f $data"</span> 0 1 2 5 15
478
-    dialog --title $<span class="org-string">"Change your avatar"</span> <span class="org-sh-escaped-newline">\</span>
479
-           --backtitle $<span class="org-string">"Freedombone Control Panel"</span> <span class="org-sh-escaped-newline">\</span>
480
-           --inputbox $<span class="org-string">"Enter a URL for an image. It should be "</span> <span class="org-sh-escaped-newline">\</span>
481
-                      $<span class="org-string">"approximately a square image."</span> 8 75 2&gt;$<span class="org-variable-name">data</span>
482
-    <span class="org-variable-name">sel</span>=$<span class="org-variable-name">?</span>
483
-    <span class="org-keyword">case</span> $<span class="org-variable-name">sel</span><span class="org-keyword"> in</span>
484
-        0)
485
-            <span class="org-variable-name">MY_FUNKY_AVATAR</span>=$(&lt;$<span class="org-variable-name">data</span>)
486
-            <span class="org-keyword">if</span> [ ${#<span class="org-variable-name">MY_FUNKY_AVATAR</span>} -gt 3 ]; <span class="org-keyword">then</span>
487
-                clear
488
-
489
-                <span class="org-comment-delimiter"># </span><span class="org-comment">do whatever is needed to change the avatar</span>
490
-                <span class="org-comment-delimiter"># </span><span class="org-comment">in your app</span>
491
-
492
-                dialog --title $<span class="org-string">"Change your avatar"</span> <span class="org-sh-escaped-newline">\</span>
493
-                       --msgbox $<span class="org-string">"Your avatar has been changed"</span> 6 40
494
-            <span class="org-keyword">fi</span>
495
-            ;;
496
-    <span class="org-keyword">esac</span>
497
-
498
-    <span class="org-comment-delimiter"># </span><span class="org-comment">install_myappname will be called automatically after this function</span>
499
-}
327
+<p>
328
+A generic PHP plus MySql/MariaDB web app which is only available on an onion address:
329
+</p>
500 330
 
501
-<span class="org-comment-delimiter"># </span><span class="org-comment">NOTE: deliberately no exit 0</span>
331
+<div class="org-src-container">
332
+<pre class="src src-bash">freedombone-template --app [name] -e [email] -r [repo url] <span class="org-sh-escaped-newline">\</span>
333
+                     -c [commit] --php yes -d mariadb <span class="org-sh-escaped-newline">\</span>
334
+                     --onion yes &gt; <span class="org-sh-escaped-newline">\</span>
335
+                     src/freedombone-app-myappname
502 336
 </pre>
503 337
 </div>
504 338
 
505 339
 <p>
506
-To test your app log into your system, select <b>Exit to command line</b> then gain root powers with:
340
+For more details see the manpage:
507 341
 </p>
508 342
 
509 343
 <div class="org-src-container">
510
-<pre class="src src-bash">sudo su
344
+<pre class="src src-bash">man freedombone-template
511 345
 </pre>
512 346
 </div>
513 347
 
514 348
 <p>
515
-Copy your app script to <b>/usr/share/freedombone/apps/freedombone-app-myappname</b>.
349
+The template command won't give you a fully working app, but it will give you a big head start and avoid a lot of potential mistakes. It's highly likely that you'll still need to add extra configuration for your particular app, especially within the <b>install_app</b> function.
516 350
 </p>
517 351
 
518 352
 <p>
519
-And run the admin control panel:
353
+When your new script is ready for testing you can install it with:
520 354
 </p>
521 355
 
522 356
 <div class="org-src-container">
523
-<pre class="src src-bash">control
357
+<pre class="src src-bash">make install
524 358
 </pre>
525 359
 </div>
526 360
 
527 361
 <p>
528
-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.
362
+Then run the administrator control panel and you should see the new app within <b>Add/Remove apps</b>.
529 363
 </p>
530 364
 
531 365
 <p>
532
-Submit your working app to <b><a href="https://github.com/bashrc/freedombone/issues">https://github.com/bashrc/freedombone/issues</a></b>
366
+Submit your working app to <b><a href="https://github.com/bashrc/freedombone/issues">https://github.com/bashrc/freedombone/issues</a></b> or create a pull request.
533 367
 </p>
534 368
 </div>
535 369
 </div>
536 370
 
537
-<div id="outline-container-orge29cd52" class="outline-2">
538
-<h2 id="orge29cd52">Customising mesh images</h2>
539
-<div class="outline-text-2" id="text-orge29cd52">
371
+<div id="outline-container-orgaefd9da" class="outline-2">
372
+<h2 id="orgaefd9da">Customising mesh images</h2>
373
+<div class="outline-text-2" id="text-orgaefd9da">
540 374
 <p>
541 375
 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.
542 376
 </p>