Pārlūkot izejas kodu

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

Bob Mottram 7 gadus atpakaļ
vecāks
revīzija
c33f236ed5

+ 4
- 0
doc/EN/app_cryptpad.org Parādīt failu

@@ -16,6 +16,10 @@
16 16
 </center>
17 17
 #+END_EXPORT
18 18
 
19
+#+BEGIN_CENTER
20
+[[file:images/cryptpad.jpg]]
21
+#+END_CENTER
22
+
19 23
 This is similar to [[./app_etherpad.html][EtherPad]] but with better security and more document types which can be collaboratively edited in real time. It includes not just text editing but also creating presentations, voting and editing source code.
20 24
 
21 25
 For added security this system is only available via an onion address, so you and your collaborators will need to be using Tor compatible browsers.

+ 39
- 0
doc/EN/app_kanboard.org Parādīt failu

@@ -0,0 +1,39 @@
1
+#+TITLE:
2
+#+AUTHOR: Bob Mottram
3
+#+EMAIL: bob@freedombone.net
4
+#+KEYWORDS: freedombone, kanboard
5
+#+DESCRIPTION: How to use KanBoard
6
+#+OPTIONS: ^:nil toc:nil
7
+#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="freedombone.css" />
8
+
9
+#+BEGIN_CENTER
10
+[[file:images/logo.png]]
11
+#+END_CENTER
12
+
13
+#+BEGIN_EXPORT html
14
+<center>
15
+<h1>KanBoard</h1>
16
+</center>
17
+#+END_EXPORT
18
+
19
+Kanbans are one way of managing projects. They're traditionally used in businesses but can also be useful for personal TODO lists or within open source or DIY projects. If you have a list of things which need to be done and want to keep track of progress then this provides a way to do that.
20
+
21
+* Installation
22
+Log into your system with:
23
+
24
+#+begin_src bash
25
+ssh myusername@mydomain -p 2222
26
+#+end_src
27
+
28
+Using cursor keys, space bar and Enter key select *Administrator controls* and type in your password.
29
+
30
+Select *Add/Remove Apps* then *kanboard*. You will then be asked for a domain name and if you are using FreeDNS also the code for the domain which can be found under *Dynamic DNS* on the FreeDNS site (the random string from "/quick cron example/" which appears after /update.php?/ and before />>/). For more details on obtaining a domain and making it accessible via dynamic DNS see the [[./faq.html][FAQ]]. Typically the domain name you use will be a subdomain, such as /kanban.mydomainname.net/. It will need to be a domain which you have bought somewhere and own and not one of the FreeDNS subdomains, otherwise you won't be able to get a SSL/TLS certificate for it.
31
+
32
+After the install has completed go to *Security settings* and select *Create a new Let's Encrypt certificate* and enter the domain name that you are using for KanBoard. If you're using the "onion only" version of the system then you don't need to do this. If the certificate is obtained successfully then you will see a congratulations message.
33
+
34
+* Initial setup
35
+If you have just obtained a Lets Encrypt certificate as above then go to *About* on the administrator control panel and you should see your KanBoard domain listed there along with an onion address. You can then navigate to your site in a browser.
36
+
37
+The default login is username "admin" and password "admin". Obviously the first thing you'll need to do is log in and change the password, which can be done by going to "My Profile" on the drop down list on the right hand side.
38
+
39
+For more details of how to use KanBoard see the [[https://kanboard.net/documentation][documentation here]].

+ 4
- 0
doc/EN/apps.org Parādīt failu

@@ -75,6 +75,10 @@ Run your own IRC chat channel which can be secured with a password and accessibl
75 75
 * Jitsi Meet
76 76
 Experimental WebRTC video conferencing system, similar to Google Hangouts. This may not be fully functional, but is hoped to be in the near future.
77 77
 
78
+* KanBoard
79
+A simple kanban system for managing projects or TODO lists.
80
+
81
+[[./app_kanboard.html][How to use it]]
78 82
 * Koel
79 83
 Access your music collection from any internet connected device.
80 84
 

Binārs
img/cryptpad.jpg Parādīt failu


+ 4
- 1
src/freedombone-app-cryptpad Parādīt failu

@@ -37,7 +37,7 @@ SHOW_ICANN_ADDRESS_ON_ABOUT=0
37 37
 CRYPTPAD_ONION_PORT=8119
38 38
 CRYPTPAD_PORT=9003
39 39
 CRYPTPAD_REPO="https://github.com/xwiki-labs/cryptpad"
40
-CRYPTPAD_COMMIT='ed5b005216be9b9029c1ccd25a5fdc7908ed8730'
40
+CRYPTPAD_COMMIT='76e69f0ba85b0e3e21cad2c3eb0012c2429d4bb8'
41 41
 CRYPTPAD_DIR=/etc/cryptpad
42 42
 
43 43
 cryptpad_variables=(ONION_ONLY)
@@ -89,6 +89,9 @@ function upgrade_cryptpad {
89 89
     set_repo_commit $CRYPTPAD_DIR "cryptpad commit" "$CRYPTPAD_COMMIT" $CRYPTPAD_REPO
90 90
 
91 91
     cd $CRYPTPAD_DIR
92
+    npm install
93
+    chown -R cryptpad:cryptpad $CRYPTPAD_DIR
94
+    su -c 'bower install' - cryptpad
92 95
 
93 96
     systemctl start cryptpad
94 97
 }

+ 2
- 2
src/freedombone-app-gogs Parādīt failu

@@ -139,7 +139,7 @@ function gogs_create_database {
139 139
     fi
140 140
 
141 141
     function_check create_database
142
-    create_database gogs "$GOGS_ADMIN_PASSWORD"
142
+    create_database gogs "$GIT_ADMIN_PASSWORD"
143 143
 }
144 144
 
145 145
 function reconfigure_gogs {
@@ -302,7 +302,7 @@ function backup_remote_gogs {
302 302
         suspend_site ${GIT_DOMAIN_NAME}
303 303
 
304 304
         function_check backup_database_to_friend
305
-        backup_database_to_friend $GOGS_USERNAME
305
+        backup_database_to_friend gogs
306 306
 
307 307
         echo $"Obtaining Gogs settings backup"
308 308
 

+ 579
- 0
src/freedombone-app-kanboard Parādīt failu

@@ -0,0 +1,579 @@
1
+#!/bin/bash
2
+#
3
+# .---.                  .              .
4
+# |                      |              |
5
+# |--- .--. .-.  .-.  .-.|  .-. .--.--. |.-.  .-. .--.  .-.
6
+# |    |   (.-' (.-' (   | (   )|  |  | |   )(   )|  | (.-'
7
+# '    '     --'  --'  -' -  -' '  '   -' -'   -' '   -  --'
8
+#
9
+#                    Freedom in the Cloud
10
+#
11
+# kanboard kanban
12
+#
13
+# License
14
+# =======
15
+#
16
+# Copyright (C) 2017 Bob Mottram <bob@freedombone.net>
17
+#
18
+# This program is free software: you can redistribute it and/or modify
19
+# it under the terms of the GNU Affero General Public License as published by
20
+# the Free Software Foundation, either version 3 of the License, or
21
+# (at your option) any later version.
22
+#
23
+# This program is distributed in the hope that it will be useful,
24
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
25
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
+# GNU Affero General Public License for more details.
27
+#
28
+# You should have received a copy of the GNU Affero General Public License
29
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
30
+
31
+VARIANTS='full full-vim social'
32
+
33
+IN_DEFAULT_INSTALL=0
34
+SHOW_ON_ABOUT=1
35
+
36
+KANBOARD_DOMAIN_NAME=
37
+KANBOARD_CODE=
38
+KANBOARD_ONION_PORT=8121
39
+KANBOARD_REPO="https://github.com/kanboard/kanboard"
40
+KANBOARD_COMMIT='7a6b1bc3da0af442e02b5a2dc430a4ded8e7c4ee'
41
+KANBOARD_ADMIN_PASSWORD=
42
+
43
+
44
+kanboard_variables=(ONION_ONLY
45
+                    KANBOARD_DOMAIN_NAME
46
+                    KANBOARD_CODE
47
+                    DDNS_PROVIDER
48
+                    MY_USERNAME)
49
+
50
+function logging_on_kanboard {
51
+    kanboard_configfile=/var/www/${KANBOARD_DOMAIN_NAME}/htdocs/config.php
52
+    sed -i "s|define('LOG_FILE'.*|define('LOG_FILE', DATA_DIR.DIRECTORY_SEPARATOR.'debug.log');|g" $kanboard_configfile
53
+}
54
+
55
+function logging_off_kanboard {
56
+    kanboard_configfile=/var/www/${KANBOARD_DOMAIN_NAME}/htdocs/config.php
57
+    sed -i "s|define('LOG_FILE'.*|define('LOG_FILE', '/dev/null');|g" $kanboard_configfile
58
+}
59
+
60
+function remove_user_kanboard {
61
+    remove_username="$1"
62
+
63
+    ${PROJECT_NAME}-pass -u $remove_username --rmapp kanboard
64
+}
65
+
66
+function add_user_kanboard {
67
+    new_username="$1"
68
+    new_user_password="$2"
69
+
70
+    ${PROJECT_NAME}-pass -u $new_username -a kanboard -p "$new_user_password"
71
+    echo '0'
72
+}
73
+
74
+function install_interactive_kanboard {
75
+    if [ ! $ONION_ONLY ]; then
76
+        ONION_ONLY='no'
77
+    fi
78
+
79
+    if [[ $ONION_ONLY != "no" ]]; then
80
+        KANBOARD_DOMAIN_NAME='kanboard.local'
81
+    else
82
+        KANBOARD_DETAILS_COMPLETE=
83
+        while [ ! $KANBOARD_DETAILS_COMPLETE ]
84
+        do
85
+            data=$(tempfile 2>/dev/null)
86
+            trap "rm -f $data" 0 1 2 5 15
87
+            if [[ $DDNS_PROVIDER == "default@freedns.afraid.org" ]]; then
88
+                dialog --backtitle $"Freedombone Configuration" \
89
+                       --title $"KanBoard Configuration" \
90
+                       --form $"\nPlease enter your KanBoard details.\n\nIMPORTANT: This should be a domain name which is supported by Let's Encrypt." 13 55 2 \
91
+                       $"Domain:" 1 1 "$(grep 'KANBOARD_DOMAIN_NAME' temp.cfg | awk -F '=' '{print $2}')" 1 15 33 40 \
92
+                       $"Code:" 2 1 "$(grep 'KANBOARD_CODE' temp.cfg | awk -F '=' '{print $2}')" 2 15 33 255 \
93
+                       2> $data
94
+            else
95
+                dialog --backtitle $"Freedombone Configuration" \
96
+                       --title $"KanBoard Configuration" \
97
+                       --form $"\nPlease enter your KanBoard details.\n\nIMPORTANT: This should be a domain name which is supported by Let's Encrypt." 13 55 2 \
98
+                       $"Domain:" 1 1 "$(grep 'KANBOARD_DOMAIN_NAME' temp.cfg | awk -F '=' '{print $2}')" 1 15 33 40 \
99
+                       2> $data
100
+            fi
101
+            sel=$?
102
+            case $sel in
103
+                1) exit 1;;
104
+                255) exit 1;;
105
+            esac
106
+            KANBOARD_DOMAIN_NAME=$(cat $data | sed -n 1p)
107
+            if [ $KANBOARD_DOMAIN_NAME ]; then
108
+                if [[ $KANBOARD_DOMAIN_NAME == "$HUBZILLA_DOMAIN_NAME" ]]; then
109
+                    KANBOARD_DOMAIN_NAME=""
110
+                fi
111
+                TEST_DOMAIN_NAME=$KANBOARD_DOMAIN_NAME
112
+                validate_domain_name
113
+                if [[ $TEST_DOMAIN_NAME != $KANBOARD_DOMAIN_NAME ]]; then
114
+                    KANBOARD_DOMAIN_NAME=
115
+                    dialog --title $"Domain name validation" --msgbox "$TEST_DOMAIN_NAME" 15 50
116
+                else
117
+                    if [[ $DDNS_PROVIDER == "default@freedns.afraid.org" ]]; then
118
+                        KANBOARD_CODE=$(cat $data | sed -n 2p)
119
+                        validate_freedns_code "$KANBOARD_CODE"
120
+                        if [ ! $VALID_CODE ]; then
121
+                            KANBOARD_DOMAIN_NAME=
122
+                        fi
123
+                    fi
124
+                fi
125
+            fi
126
+            if [ $KANBOARD_DOMAIN_NAME ]; then
127
+                KANBOARD_DETAILS_COMPLETE="yes"
128
+            fi
129
+        done
130
+
131
+        # save the results in the config file
132
+        write_config_param "KANBOARD_CODE" "$KANBOARD_CODE"
133
+    fi
134
+    write_config_param "KANBOARD_DOMAIN_NAME" "$KANBOARD_DOMAIN_NAME"
135
+    APP_INSTALLED=1
136
+}
137
+
138
+function change_password_kanboard {
139
+    curr_username="$1"
140
+    new_user_password="$2"
141
+
142
+    read_config_param 'KANBOARD_DOMAIN_NAME'
143
+
144
+    ${PROJECT_NAME}-pass -u "$curr_username" -a kanboard -p "$new_user_password"
145
+}
146
+
147
+function kanboard_create_database {
148
+    if [ -f $IMAGE_PASSWORD_FILE ]; then
149
+        KANBOARD_ADMIN_PASSWORD="$(printf `cat $IMAGE_PASSWORD_FILE`)"
150
+    else
151
+        if [ ! $KANBOARD_ADMIN_PASSWORD ]; then
152
+            KANBOARD_ADMIN_PASSWORD="$(create_password ${MINIMUM_PASSWORD_LENGTH})"
153
+        fi
154
+    fi
155
+    if [ ! $KANBOARD_ADMIN_PASSWORD ]; then
156
+        return
157
+    fi
158
+
159
+    function_check create_database
160
+    create_database kanboard "$KANBOARD_ADMIN_PASSWORD" $MY_USERNAME
161
+}
162
+
163
+function reconfigure_kanboard {
164
+    echo -n ''
165
+}
166
+
167
+function upgrade_kanboard {
168
+    CURR_KANBOARD_COMMIT=$(get_completion_param "kanboard commit")
169
+    if [[ "$CURR_KANBOARD_COMMIT" == "$KANBOARD_COMMIT" ]]; then
170
+        return
171
+    fi
172
+
173
+    if grep -q "kanboard domain" $COMPLETION_FILE; then
174
+        KANBOARD_DOMAIN_NAME=$(get_completion_param "kanboard domain")
175
+    fi
176
+
177
+    # update to the next commit
178
+    function_check set_repo_commit
179
+    set_repo_commit /var/www/$KANBOARD_DOMAIN_NAME/htdocs "kanboard commit" "$KANBOARD_COMMIT" $KANBOARD_REPO
180
+
181
+    chown -R www-data:www-data /var/www/${KANBOARD_DOMAIN_NAME}/htdocs
182
+}
183
+
184
+
185
+function backup_local_kanboard {
186
+    KANBOARD_DOMAIN_NAME='kanboard'
187
+    if grep -q "kanboard domain" $COMPLETION_FILE; then
188
+        KANBOARD_DOMAIN_NAME=$(get_completion_param "kanboard domain")
189
+    fi
190
+
191
+    source_directory=/var/www/${KANBOARD_DOMAIN_NAME}/htdocs/backup
192
+    if [ ! -d $source_directory ]; then
193
+        mkdir $source_directory
194
+    fi
195
+    cp -p /var/www/${KANBOARD_DOMAIN_NAME}/htdocs/config.php $source_directory
196
+
197
+    function_check suspend_site
198
+    suspend_site ${KANBOARD_DOMAIN_NAME}
199
+
200
+    function_check backup_directory_to_usb
201
+    dest_directory=kanboardconfig
202
+    backup_directory_to_usb $source_directory $dest_directory
203
+
204
+    source_directory=/var/www/${KANBOARD_DOMAIN_NAME}/htdocs/data
205
+    dest_directory=kanboardfile
206
+    backup_directory_to_usb $source_directory $dest_directory
207
+
208
+    function_check backup_database_to_usb
209
+    backup_database_to_usb kanboard
210
+
211
+    function_check restart_site
212
+    restart_site
213
+}
214
+
215
+function restore_local_kanboard {
216
+    if ! grep -q "kanboard domain" $COMPLETION_FILE; then
217
+        return
218
+    fi
219
+    KANBOARD_DOMAIN_NAME=$(get_completion_param "kanboard domain")
220
+    if [ $KANBOARD_DOMAIN_NAME ]; then
221
+        echo $"Restoring kanboard"
222
+        temp_restore_dir=/root/tempkanboard
223
+        kanboard_dir=/var/www/${KANBOARD_DOMAIN_NAME}/htdocs
224
+
225
+        function_check kanboard_create_database
226
+        kanboard_create_database
227
+
228
+        restore_database kanboard
229
+        if [ -d $temp_restore_dir ]; then
230
+            rm -rf $temp_restore_dir
231
+        fi
232
+
233
+        function_check restore_directory_from_usb
234
+        restore_directory_from_usb $temp_restore_dir kanboardconfig
235
+        if [ -d $temp_restore_dir ]; then
236
+            cp $temp_restore_dir$kanboard_dir/backup/config.php $kanboard_dir/
237
+            chown www-data:www-data $kanboard_dir/config.php
238
+            rm -rf $temp_restore_dir
239
+        fi
240
+
241
+        restore_directory_from_usb $temp_restore_dir kanboardfile
242
+        if [ -d $temp_restore_dir ]; then
243
+            cp -rp $temp_restore_dir$kanboard_dir/data $kanboard_dir/
244
+            chown -R www-data:www-data $kanboard_dir/data
245
+            rm -rf $temp_restore_dir
246
+        fi
247
+
248
+        kanboard_update_after_restore kanboard ${KANBOARD_DOMAIN_NAME}
249
+
250
+        echo $"Restore of kanboard complete"
251
+    fi
252
+}
253
+
254
+function backup_remote_kanboard {
255
+    KANBOARD_DOMAIN_NAME='kanboard'
256
+    if grep -q "kanboard domain" $COMPLETION_FILE; then
257
+        KANBOARD_DOMAIN_NAME=$(get_completion_param "kanboard domain")
258
+    fi
259
+
260
+    source_directory=/var/www/${KANBOARD_DOMAIN_NAME}/htdocs/backup
261
+    if [ ! -d $source_directory ]; then
262
+        mkdir $source_directory
263
+    fi
264
+    cp -p /var/www/${KANBOARD_DOMAIN_NAME}/htdocs/config.php $source_directory
265
+
266
+    function_check suspend_site
267
+    suspend_site ${KANBOARD_DOMAIN_NAME}
268
+
269
+    function_check backup_directory_to_friend
270
+    dest_directory=kanboardconfig
271
+    backup_directory_to_friend $source_directory $dest_directory
272
+
273
+    source_directory=/var/www/${KANBOARD_DOMAIN_NAME}/htdocs/data
274
+    dest_directory=kanboardfile
275
+    backup_directory_to_friend $source_directory $dest_directory
276
+
277
+    function_check backup_database_to_friend
278
+    backup_database_to_friend kanboard
279
+
280
+    function_check restart_site
281
+    restart_site
282
+}
283
+
284
+function restore_remote_kanboard {
285
+    if ! grep -q "kanboard domain" $COMPLETION_FILE; then
286
+        return
287
+    fi
288
+    KANBOARD_DOMAIN_NAME=$(get_completion_param "kanboard domain")
289
+    if [ $KANBOARD_DOMAIN_NAME ]; then
290
+        echo $"Restoring kanboard"
291
+        temp_restore_dir=/root/tempkanboard
292
+        kanboard_dir=/var/www/${KANBOARD_DOMAIN_NAME}/htdocs
293
+
294
+        function_check kanboard_create_database
295
+        kanboard_create_database
296
+
297
+        function_check restore_database_from_friend
298
+        restore_database_from_friend kanboard
299
+        if [ -d $temp_restore_dir ]; then
300
+            rm -rf $temp_restore_dir
301
+        fi
302
+
303
+        function_check restore_directory_from_friend
304
+        restore_directory_from_friend $temp_restore_dir kanboardconfig
305
+        if [ -d $temp_restore_dir ]; then
306
+            cp $temp_restore_dir$kanboard_dir/backup/config.php $kanboard_dir/
307
+            chown www-data:www-data $kanboard_dir/config.php
308
+            rm -rf $temp_restore_dir
309
+        fi
310
+
311
+        restore_directory_from_friend $temp_restore_dir kanboardfile
312
+        if [ -d $temp_restore_dir ]; then
313
+            cp -rp $temp_restore_dir$kanboard_dir/data $kanboard_dir/
314
+            chown -R www-data:www-data $kanboard_dir/data
315
+            rm -rf $temp_restore_dir
316
+        fi
317
+
318
+        kanboard_update_after_restore kanboard ${KANBOARD_DOMAIN_NAME}
319
+
320
+        echo $"Restore of kanboard complete"
321
+    fi
322
+}
323
+
324
+function remove_kanboard {
325
+    if [ ${#KANBOARD_DOMAIN_NAME} -eq 0 ]; then
326
+        return
327
+    fi
328
+    read_config_param "KANBOARD_DOMAIN_NAME"
329
+    read_config_param "MY_USERNAME"
330
+    echo "Removing $KANBOARD_DOMAIN_NAME"
331
+    nginx_dissite $KANBOARD_DOMAIN_NAME
332
+    remove_certs $KANBOARD_DOMAIN_NAME
333
+
334
+    if [ -d /var/www/$KANBOARD_DOMAIN_NAME ]; then
335
+        rm -rf /var/www/$KANBOARD_DOMAIN_NAME
336
+    fi
337
+    if [ -f /etc/nginx/sites-available/$KANBOARD_DOMAIN_NAME ]; then
338
+        rm /etc/nginx/sites-available/$KANBOARD_DOMAIN_NAME
339
+    fi
340
+    function_check drop_database
341
+    drop_database kanboard
342
+    function_check remove_onion_service
343
+    remove_onion_service kanboard ${KANBOARD_ONION_PORT}
344
+    remove_app kanboard
345
+    remove_completion_param install_kanboard
346
+    sed -i '/kanboard/d' $COMPLETION_FILE
347
+    remove_backup_database_local kanboard
348
+
349
+    function_check remove_ddns_domain
350
+    remove_ddns_domain $KANBOARD_DOMAIN_NAME
351
+}
352
+
353
+function install_kanboard {
354
+    if [ ! $ONION_ONLY ]; then
355
+        ONION_ONLY='no'
356
+    fi
357
+
358
+    if [ ! $KANBOARD_DOMAIN_NAME ]; then
359
+        echo $'No domain name was given for kanboard'
360
+        exit 73478
361
+    fi
362
+
363
+    kanboard_hourly_script kanboard $KANBOARD_DOMAIN_NAME
364
+
365
+    function_check install_mariadb
366
+    install_mariadb
367
+
368
+    function_check get_mariadb_password
369
+    get_mariadb_password
370
+
371
+    function_check repair_databases_script
372
+    repair_databases_script
373
+
374
+    apt-get -yq install php-gettext php-curl php-gd php-mysql git curl
375
+    apt-get -yq install memcached php-memcached php-intl exiftool libfcgi0ldbl
376
+
377
+    if [ ! -d /var/www/$KANBOARD_DOMAIN_NAME ]; then
378
+        mkdir /var/www/$KANBOARD_DOMAIN_NAME
379
+    fi
380
+    if [ ! -d /var/www/$KANBOARD_DOMAIN_NAME/htdocs ]; then
381
+
382
+        if [ -d /repos/kanboard ]; then
383
+            mkdir /var/www/$KANBOARD_DOMAIN_NAME/htdocs
384
+            cp -r -p /repos/kanboard/. /var/www/$KANBOARD_DOMAIN_NAME/htdocs
385
+            cd /var/www/$KANBOARD_DOMAIN_NAME/htdocs
386
+            git pull
387
+        else
388
+            function_check git_clone
389
+            git_clone $KANBOARD_REPO /var/www/$KANBOARD_DOMAIN_NAME/htdocs
390
+        fi
391
+
392
+        if [ ! -d /var/www/$KANBOARD_DOMAIN_NAME/htdocs ]; then
393
+            echo $'Unable to clone kanboard repo'
394
+            exit 89365
395
+        fi
396
+    fi
397
+
398
+    cd /var/www/$KANBOARD_DOMAIN_NAME/htdocs
399
+    git checkout $KANBOARD_COMMIT -b $KANBOARD_COMMIT
400
+    set_completion_param "kanboard commit" "$KANBOARD_COMMIT"
401
+
402
+    chmod g+w /var/www/$KANBOARD_DOMAIN_NAME/htdocs
403
+    chmod a+w /var/www/$KANBOARD_DOMAIN_NAME/htdocs/data
404
+    chown -R www-data:www-data /var/www/$KANBOARD_DOMAIN_NAME/htdocs
405
+
406
+    function_check kanboard_create_database
407
+    kanboard_create_database
408
+
409
+    if [ ! -f "/etc/aliases" ]; then
410
+        touch /etc/aliases
411
+    fi
412
+    if ! grep -q "www-data: root" /etc/aliases; then
413
+        echo 'www-data: root' >> /etc/aliases
414
+    fi
415
+
416
+    function_check add_ddns_domain
417
+    add_ddns_domain $KANBOARD_DOMAIN_NAME
418
+
419
+    KANBOARD_ONION_HOSTNAME=$(add_onion_service kanboard 80 ${KANBOARD_ONION_PORT})
420
+
421
+    kanboard_nginx_site=/etc/nginx/sites-available/$KANBOARD_DOMAIN_NAME
422
+    if [[ $ONION_ONLY == "no" ]]; then
423
+        function_check nginx_http_redirect
424
+        nginx_http_redirect $KANBOARD_DOMAIN_NAME "index index.php"
425
+        echo 'server {' >> $kanboard_nginx_site
426
+        echo '  listen 443 ssl;' >> $kanboard_nginx_site
427
+        echo '  listen [::]:443 ssl;' >> $kanboard_nginx_site
428
+        echo "  server_name $KANBOARD_DOMAIN_NAME;" >> $kanboard_nginx_site
429
+        echo '' >> $kanboard_nginx_site
430
+        function_check nginx_compress
431
+        nginx_compress $KANBOARD_DOMAIN_NAME
432
+        echo '' >> $kanboard_nginx_site
433
+        echo '  # Security' >> $kanboard_nginx_site
434
+        function_check nginx_ssl
435
+        nginx_ssl $KANBOARD_DOMAIN_NAME
436
+
437
+        function_check nginx_disable_sniffing
438
+        nginx_disable_sniffing $KANBOARD_DOMAIN_NAME
439
+
440
+        echo '  add_header Strict-Transport-Security max-age=15768000;' >> $kanboard_nginx_site
441
+        echo '' >> $kanboard_nginx_site
442
+        echo '  # Logs' >> $kanboard_nginx_site
443
+        echo '  access_log /dev/null;' >> $kanboard_nginx_site
444
+        echo '  error_log /dev/null;' >> $kanboard_nginx_site
445
+        echo '' >> $kanboard_nginx_site
446
+        echo '  # Root' >> $kanboard_nginx_site
447
+        echo "  root /var/www/$KANBOARD_DOMAIN_NAME/htdocs;" >> $kanboard_nginx_site
448
+        echo '' >> $kanboard_nginx_site
449
+        echo '  # Index' >> $kanboard_nginx_site
450
+        echo '  index index.php;' >> $kanboard_nginx_site
451
+        echo '' >> $kanboard_nginx_site
452
+        echo '  # PHP' >> $kanboard_nginx_site
453
+        echo '  location ~ \.php {' >> $kanboard_nginx_site
454
+        echo '    include snippets/fastcgi-php.conf;' >> $kanboard_nginx_site
455
+        echo '    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;' >> $kanboard_nginx_site
456
+        echo '    fastcgi_read_timeout 30;' >> $kanboard_nginx_site
457
+        echo '  }' >> $kanboard_nginx_site
458
+        echo '' >> $kanboard_nginx_site
459
+        echo '  # Location' >> $kanboard_nginx_site
460
+        echo '  location / {' >> $kanboard_nginx_site
461
+        function_check nginx_limits
462
+        nginx_limits $KANBOARD_DOMAIN_NAME '15m'
463
+        echo '    try_files $uri $uri/ @kanboard;' >> $kanboard_nginx_site
464
+        echo '  }' >> $kanboard_nginx_site
465
+        echo '' >> $kanboard_nginx_site
466
+        echo '  # Fancy URLs' >> $kanboard_nginx_site
467
+        echo '  location @kanboard {' >> $kanboard_nginx_site
468
+        echo '    rewrite ^(.*)$ /index.php?p=$1 last;' >> $kanboard_nginx_site
469
+        echo '  }' >> $kanboard_nginx_site
470
+        echo '' >> $kanboard_nginx_site
471
+        echo '  # Restrict access that is unnecessary anyway' >> $kanboard_nginx_site
472
+        echo '  location ~ /\.(ht|git) {' >> $kanboard_nginx_site
473
+        echo '    deny all;' >> $kanboard_nginx_site
474
+        echo '  }' >> $kanboard_nginx_site
475
+        echo '' >> $kanboard_nginx_site
476
+        # DO NOT ENABLE KEYBASE. kanboard really doesn't like having a .well-known directory
477
+        echo '}' >> $kanboard_nginx_site
478
+    else
479
+        echo -n '' > $kanboard_nginx_site
480
+    fi
481
+    echo 'server {' >> $kanboard_nginx_site
482
+    echo "    listen 127.0.0.1:$KANBOARD_ONION_PORT default_server;" >> $kanboard_nginx_site
483
+    echo "    server_name $KANBOARD_ONION_HOSTNAME;" >> $kanboard_nginx_site
484
+    echo '' >> $kanboard_nginx_site
485
+    function_check nginx_compress
486
+    nginx_compress $KANBOARD_DOMAIN_NAME
487
+    echo '' >> $kanboard_nginx_site
488
+    function_check nginx_disable_sniffing
489
+    nginx_disable_sniffing $KANBOARD_DOMAIN_NAME
490
+    echo '' >> $kanboard_nginx_site
491
+    echo '  # Logs' >> $kanboard_nginx_site
492
+    echo '  access_log /dev/null;' >> $kanboard_nginx_site
493
+    echo '  error_log /dev/null;' >> $kanboard_nginx_site
494
+    echo '' >> $kanboard_nginx_site
495
+    echo '  # Root' >> $kanboard_nginx_site
496
+    echo "  root /var/www/$KANBOARD_DOMAIN_NAME/htdocs;" >> $kanboard_nginx_site
497
+    echo '' >> $kanboard_nginx_site
498
+    echo '  # Index' >> $kanboard_nginx_site
499
+    echo '  index index.php;' >> $kanboard_nginx_site
500
+    echo '' >> $kanboard_nginx_site
501
+    echo '  # PHP' >> $kanboard_nginx_site
502
+    echo '  location ~ \.php {' >> $kanboard_nginx_site
503
+    echo '    include snippets/fastcgi-php.conf;' >> $kanboard_nginx_site
504
+    echo '    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;' >> $kanboard_nginx_site
505
+    echo '    fastcgi_read_timeout 30;' >> $kanboard_nginx_site
506
+    echo '  }' >> $kanboard_nginx_site
507
+    echo '' >> $kanboard_nginx_site
508
+    echo '  # Location' >> $kanboard_nginx_site
509
+    echo '  location / {' >> $kanboard_nginx_site
510
+    function_check nginx_limits
511
+    nginx_limits $KANBOARD_DOMAIN_NAME '15m'
512
+    echo '    try_files $uri $uri/ @kanboard;' >> $kanboard_nginx_site
513
+    echo '  }' >> $kanboard_nginx_site
514
+    echo '' >> $kanboard_nginx_site
515
+    echo '  # Fancy URLs' >> $kanboard_nginx_site
516
+    echo '  location @kanboard {' >> $kanboard_nginx_site
517
+    echo '    rewrite ^(.*)$ /index.php?p=$1 last;' >> $kanboard_nginx_site
518
+    echo '  }' >> $kanboard_nginx_site
519
+    echo '' >> $kanboard_nginx_site
520
+    echo '  # Restrict access that is unnecessary anyway' >> $kanboard_nginx_site
521
+    echo '  location ~ /\.(ht|git) {' >> $kanboard_nginx_site
522
+    echo '    deny all;' >> $kanboard_nginx_site
523
+    echo '  }' >> $kanboard_nginx_site
524
+    echo '' >> $kanboard_nginx_site
525
+    # DO NOT ENABLE KEYBASE. kanboard really doesn't like having a .well-known directory
526
+    echo '}' >> $kanboard_nginx_site
527
+
528
+    function_check configure_php
529
+    configure_php
530
+
531
+    function_check create_site_certificate
532
+    create_site_certificate $KANBOARD_DOMAIN_NAME 'yes'
533
+
534
+    # Ensure that the database gets backed up locally, if remote
535
+    # backups are not being used
536
+    function_check backup_databases_script_header
537
+    backup_databases_script_header
538
+
539
+    function_check backup_database_local
540
+    backup_database_local kanboard
541
+
542
+    function_check nginx_ensite
543
+    nginx_ensite $KANBOARD_DOMAIN_NAME
544
+
545
+    KANBOARD_SERVER=${KANBOARD_DOMAIN_NAME}
546
+    if [[ $ONION_ONLY != 'no' ]]; then
547
+        KANBOARD_SERVER=${KANBOARD_ONION_HOSTNAME}
548
+    fi
549
+
550
+    # Create the configuration
551
+    kanboard_configfile=/var/www/${KANBOARD_DOMAIN_NAME}/htdocs/config.php
552
+    cp /var/www/${KANBOARD_DOMAIN_NAME}/htdocs/config.default.php $kanboard_configfile
553
+    sed -i "s|define('MAIL_FROM'.*|define('MAIL_FROM', '$MY_EMAIL_ADDRESS');|g" $kanboard_configfile
554
+    sed -i "s|define('DB_DRIVER'.*|define('DB_DRIVER', 'mysql');|g" $kanboard_configfile
555
+    sed -i "s|define('DB_USERNAME'.*|define('DB_USERNAME', 'root');|g" $kanboard_configfile
556
+    sed -i "s|define('DB_PASSWORD'.*|define('DB_PASSWORD', '$MARIADB_PASSWORD');|g" $kanboard_configfile
557
+    sed -i "s|define('DB_HOSTNAME'.*|define('DB_HOSTNAME', 'localhost');|g" $kanboard_configfile
558
+    sed -i "s|define('DB_NAME'.*|define('DB_NAME', 'kanboard');|g" $kanboard_configfile
559
+    sed -i "s|define('DB_PORT'.*|define('DB_PORT', null);|g" $kanboard_configfile
560
+    logging_off_kanboard
561
+
562
+    initialise_database kanboard /var/www/${KANBOARD_DOMAIN_NAME}/htdocs/app/Schema/Sql/mysql.sql
563
+    chown -R www-data:www-data /var/www/${KANBOARD_DOMAIN_NAME}/htdocs
564
+
565
+    cd /var/www/${KANBOARD_DOMAIN_NAME}/htdocs
566
+    install_composer
567
+
568
+    systemctl restart mariadb
569
+    systemctl restart php7.0-fpm
570
+    systemctl restart nginx
571
+
572
+    ${PROJECT_NAME}-pass -u $MY_USERNAME -a kanboard -p "$KANBOARD_ADMIN_PASSWORD"
573
+
574
+    set_completion_param "kanboard domain" "$KANBOARD_DOMAIN_NAME"
575
+
576
+    APP_INSTALLED=1
577
+}
578
+
579
+# NOTE: deliberately there is no "exit 0"

+ 1
- 13
src/freedombone-app-koel Parādīt failu

@@ -715,21 +715,9 @@ function install_koel {
715 715
     install_koel_main
716 716
 
717 717
     cd /var/www/$KOEL_DOMAIN_NAME/htdocs
718
+    install_composer
718 719
 
719
-    # curl -sS https://getcomposer.org/installer | php
720
-    if [ -f ~/freedombone/image_build/composer_install ]; then
721
-        cat ~/freedombone/image_build/composer_install | php
722
-    else
723
-        if [ -f /home/$MY_USERNAME/freedombone/image_build/composer_install ]; then
724
-            cat /home/$MY_USERNAME/freedombone/image_build/composer_install | php
725
-        fi
726
-    fi
727 720
     npm install -g yarn
728
-    php composer.phar install
729
-    if [ ! "$?" = "0" ]; then
730
-        echo $'Unable to run composer install'
731
-        exit 7252198
732
-    fi
733 721
     npm install
734 722
 
735 723
     function_check get_mariadb_password

+ 2
- 9
src/freedombone-app-movim Parādīt failu

@@ -383,15 +383,8 @@ function install_movim {
383 383
     # Fix typo
384 384
     sed -i 's|weksocket|websocket|g' app/widgets/AdminTest/admintest.js
385 385
 
386
-    # curl -sS https://getcomposer.org/installer | php
387
-    if [ -f ~/freedombone/image_build/composer_install ]; then
388
-        cat ~/freedombone/image_build/composer_install | php
389
-    else
390
-        if [ -f /home/$MY_USERNAME/freedombone/image_build/composer_install ]; then
391
-            cat /home/$MY_USERNAME/freedombone/image_build/composer_install | php
392
-        fi
393
-    fi
394
-    php composer.phar install
386
+    cd /var/www/$MOVIM_DOMAIN_NAME/htdocs
387
+    install_composer
395 388
 
396 389
     cd /var/www/$MOVIM_DOMAIN_NAME/htdocs/config
397 390
     cp db.example.inc.php db.inc.php

+ 13
- 5
src/freedombone-app-profanity Parādīt failu

@@ -34,13 +34,13 @@ IN_DEFAULT_INSTALL=0
34 34
 SHOW_ON_ABOUT=1
35 35
 
36 36
 LIBMESODE_REPO="https://github.com/boothj5/libmesode"
37
-LIBMESODE_COMMIT='e3db0e9bfba61b2d82193874343a94a88f910800'
37
+LIBMESODE_COMMIT='b91872cf7e7ed4d2443ab5c622f4cdb395d64dbe'
38 38
 
39 39
 PROFANITY_REPO="https://github.com/boothj5/profanity"
40
-PROFANITY_COMMIT='2fafaec8a7dc9bc01ee894d83214590598b32914'
40
+PROFANITY_COMMIT='f8b855b09f2c4e9b461b0b7854afabbecf6d5b4a'
41 41
 
42 42
 PROFANITY_OMEMO_PLUGIN_REPO="https://github.com/ReneVolution/profanity-omemo-plugin"
43
-PROFANITY_OMEMO_PLUGIN_COMMIT='3ec8ec173656bed9761b740b086123e07c749548'
43
+PROFANITY_OMEMO_PLUGIN_COMMIT='78be0c8367c6379829986755c0d1da287c031234'
44 44
 
45 45
 xmpp_variables=(ONION_ONLY
46 46
                 INSTALLED_WITHIN_DOCKER
@@ -285,7 +285,11 @@ function install_profanity {
285 285
         echo 'enabled=true' >> $XMPP_CLIENT_ACCOUNTS
286 286
         echo "jid=${MY_USERNAME}@${DEFAULT_DOMAIN_NAME}" >> $XMPP_CLIENT_ACCOUNTS
287 287
         echo "server=$XMPP_ONION_HOSTNAME" >> $XMPP_CLIENT_ACCOUNTS
288
-        echo "pgp.keyid=$MY_GPG_PUBLIC_KEY_ID" >> $XMPP_CLIENT_ACCOUNTS
288
+        # There is a bug where profanity doesn't refresh the screen
289
+        # after gpg-agent has asked for a password, so for now
290
+        # don't set the gpg key by default
291
+        #echo "pgp.keyid=$MY_GPG_PUBLIC_KEY_ID" >> $XMPP_CLIENT_ACCOUNTS
292
+        echo "pgp.keyid=" >> $XMPP_CLIENT_ACCOUNTS
289 293
         echo 'resource=profanity' >> $XMPP_CLIENT_ACCOUNTS
290 294
         echo "muc.service=chat.${DEFAULT_DOMAIN_NAME}" >> $XMPP_CLIENT_ACCOUNTS
291 295
         echo "muc.nick=${MY_USERNAME}" >> $XMPP_CLIENT_ACCOUNTS
@@ -310,7 +314,11 @@ function install_profanity {
310 314
         fi
311 315
         echo "jid=${MY_USERNAME}@${XMPP_ONION_HOSTNAME}" >> $XMPP_CLIENT_ACCOUNTS
312 316
         echo "server=$XMPP_ONION_HOSTNAME" >> $XMPP_CLIENT_ACCOUNTS
313
-        echo "pgp.keyid=$MY_GPG_PUBLIC_KEY_ID" >> $XMPP_CLIENT_ACCOUNTS
317
+        # There is a bug where profanity doesn't refresh the screen
318
+        # after gpg-agent has asked for a password, so for now
319
+        # don't set the gpg key by default
320
+        #echo "pgp.keyid=$MY_GPG_PUBLIC_KEY_ID" >> $XMPP_CLIENT_ACCOUNTS
321
+        echo "pgp.keyid=" >> $XMPP_CLIENT_ACCOUNTS
314 322
         echo 'resource=profanity' >> $XMPP_CLIENT_ACCOUNTS
315 323
         echo "muc.service=${XMPP_ONION_HOSTNAME}" >> $XMPP_CLIENT_ACCOUNTS
316 324
         echo "muc.nick=${MY_USERNAME}" >> $XMPP_CLIENT_ACCOUNTS

+ 494
- 0
src/freedombone-app-wekan Parādīt failu

@@ -0,0 +1,494 @@
1
+#!/bin/bash
2
+#
3
+# .---.                  .              .
4
+# |                      |              |
5
+# |--- .--. .-.  .-.  .-.|  .-. .--.--. |.-.  .-. .--.  .-.
6
+# |    |   (.-' (.-' (   | (   )|  |  | |   )(   )|  | (.-'
7
+# '    '     --'  --'  -' -  -' '  '   -' -'   -' '   -  --'
8
+#
9
+#                    Freedom in the Cloud
10
+#
11
+# Wekan kanban
12
+#
13
+# License
14
+# =======
15
+#
16
+# Copyright (C) 2017 Bob Mottram <bob@freedombone.net>
17
+#
18
+# This program is free software: you can redistribute it and/or modify
19
+# it under the terms of the GNU Affero General Public License as published by
20
+# the Free Software Foundation, either version 3 of the License, or
21
+# (at your option) any later version.
22
+#
23
+# This program is distributed in the hope that it will be useful,
24
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
25
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
+# GNU Affero General Public License for more details.
27
+#
28
+# You should have received a copy of the GNU Affero General Public License
29
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
30
+
31
+VARIANTS=''
32
+
33
+IN_DEFAULT_INSTALL=0
34
+SHOW_ON_ABOUT=0
35
+
36
+WEKAN_DOMAIN_NAME=
37
+WEKAN_CODE=
38
+WEKAN_PORT=8081
39
+WEKAN_ONION_PORT=8120
40
+WEKAN_REPO="https://github.com/wekan/wekan"
41
+WEKAN_COMMIT='dc547c38d1f5ca72729f6d8f81eb03671ca15934'
42
+FLOW_ROUTER_REPO="git://github.com/wekan/flow-router.git"
43
+FLOW_ROUTER_COMMIT='0c1f6423ed9b68eb00cfb1a19492438917a38956'
44
+WEKAN_DIR=/etc/wekan
45
+
46
+wekan_variables=(ONION_ONLY
47
+                 WEKAN_DOMAIN_NAME
48
+                 WEKAN_CODE
49
+                 DDNS_PROVIDER
50
+                 MY_USERNAME)
51
+
52
+function logging_on_wekan {
53
+    echo -n ''
54
+}
55
+
56
+function logging_off_wekan {
57
+    echo -n ''
58
+}
59
+
60
+function remove_user_wekan {
61
+    remove_username="$1"
62
+}
63
+
64
+function add_user_wekan {
65
+    new_username="$1"
66
+    new_user_password="$2"
67
+    echo '0'
68
+}
69
+
70
+function install_interactive_wekan {
71
+    if [[ $ONION_ONLY != "no" ]]; then
72
+        GIT_DOMAIN_NAME='wekan.local'
73
+        write_config_param "WEKAN_DOMAIN_NAME" "$WEKAN_DOMAIN_NAME"
74
+    else
75
+        function_check interactive_site_details
76
+        interactive_site_details wekan
77
+    fi
78
+    APP_INSTALLED=1
79
+}
80
+
81
+function change_password_wekan {
82
+    curr_username="$1"
83
+    new_user_password="$2"
84
+}
85
+
86
+function reconfigure_wekan {
87
+    echo -n ''
88
+}
89
+
90
+function upgrade_wekan {
91
+    CURR_WEKAN_COMMIT=$(get_completion_param "wekan commit")
92
+    if [[ "$CURR_WEKAN_COMMIT" == "$WEKAN_COMMIT" ]]; then
93
+        return
94
+    fi
95
+
96
+    systemctl stop wekan
97
+
98
+    # update to the next commit
99
+    function_check set_repo_commit
100
+    set_repo_commit $WEKAN_DIR "wekan commit" "$WEKAN_COMMIT" $WEKAN_REPO
101
+
102
+    systemctl start wekan
103
+}
104
+
105
+function backup_local_wekan {
106
+    source_directory=$WEKAN_DIR/data
107
+    if [ -d $source_directory ]; then
108
+        systemctl stop wekan
109
+
110
+        dest_directory=wekan
111
+        function_check suspend_site
112
+        suspend_site wekan
113
+
114
+        function_check backup_database_to_usb
115
+        backup_database_to_usb wekan
116
+
117
+        function_check backup_directory_to_usb
118
+        backup_directory_to_usb $source_directory $dest_directory
119
+
120
+        function_check restart_site
121
+        restart_site
122
+
123
+        systemctl start wekan
124
+    fi
125
+}
126
+
127
+function restore_local_wekan {
128
+    if [ -d $WEKAN_DIR ]; then
129
+        systemctl stop wekan
130
+
131
+        function_check restore_database
132
+        restore_database gogs ${WEKAN_DOMAIN_NAME}
133
+
134
+        temp_restore_dir=/root/tempwekan
135
+        function_check restore_directory_from_usb
136
+        restore_directory_from_usb $temp_restore_dir wekan
137
+        cp -r $temp_restore_dir$WEKAN_DIR/data/* $WEKAN_DIR/data/
138
+
139
+        systemctl start wekan
140
+    fi
141
+}
142
+
143
+function backup_remote_wekan {
144
+    if grep -q "wekan domain" $COMPLETION_FILE; then
145
+        temp_backup_dir=$WEKAN_DIR/data
146
+        if [ -d $temp_backup_dir ]; then
147
+            systemctl stop wekan
148
+
149
+            function_check suspend_site
150
+            suspend_site wekan
151
+
152
+            echo $"Backing up Wekan installation"
153
+
154
+            function_check backup_database_to_friend
155
+            backup_database_to_friend wekan
156
+
157
+            function_check backup_directory_to_friend
158
+            backup_directory_to_friend $temp_backup_dir wekan
159
+
160
+            function_check restart_site
161
+            restart_site
162
+
163
+            systemctl start wekan
164
+        else
165
+            echo $"wekan domain specified but not found in ${temp_backup_dir}"
166
+        fi
167
+    fi
168
+}
169
+
170
+function restore_remote_wekan {
171
+    if [ -d $WEKAN_DIR ]; then
172
+        systemctl stop wekan
173
+
174
+        function_check restore_database_from_friend
175
+        restore_database_from_friend wekan
176
+
177
+        temp_restore_dir=/root/tempwekan
178
+        function_check restore_directory_from_usb
179
+        restore_directory_from_friend $temp_restore_dir wekan
180
+        cp -r $temp_restore_dir$WEKAN_DIR/data/* $WEKAN_DIR/data/
181
+
182
+        systemctl start wekan
183
+    fi
184
+}
185
+
186
+function remove_wekan {
187
+    systemctl stop wekan
188
+    systemctl disable wekan
189
+    if [ -f /etc/systemd/system/wekan.service ]; then
190
+        rm /etc/systemd/system/wekan.service
191
+    fi
192
+    systemctl daemon-reload
193
+
194
+    function_check remove_nodejs
195
+    remove_nodejs wekan
196
+
197
+    nginx_dissite wekan
198
+
199
+    if [ -d $WEKAN_DIR ]; then
200
+        rm -rf $WEKAN_DIR
201
+    fi
202
+    if [ -f /etc/nginx/sites-available/wekan ]; then
203
+        rm /etc/nginx/sites-available/wekan
204
+    fi
205
+    function_check drop_database
206
+    drop_database wekan
207
+    function_check remove_onion_service
208
+    remove_onion_service wekan ${WEKAN_ONION_PORT}
209
+    remove_app wekan
210
+    remove_completion_param install_wekan
211
+    sed -i '/wekan/d' $COMPLETION_FILE
212
+
213
+    groupdel -f gogs
214
+    userdel -r wekan
215
+    remove_meteor
216
+}
217
+
218
+function wekan_create_database {
219
+    if [ -f ${IMAGE_PASSWORD_FILE} ]; then
220
+        WEKAN_ADMIN_PASSWORD="$(printf `cat $IMAGE_PASSWORD_FILE`)"
221
+    else
222
+        if [ ! ${GIT_ADMIN_PASSWORD} ]; then
223
+            WEKAN_ADMIN_PASSWORD="$(create_password ${MINIMUM_PASSWORD_LENGTH})"
224
+        fi
225
+    fi
226
+    if [ ! $WEKAN_ADMIN_PASSWORD ]; then
227
+        return
228
+    fi
229
+
230
+    function_check create_database
231
+    create_database gogs "$WEKAN_ADMIN_PASSWORD"
232
+}
233
+
234
+function install_wekan_main {
235
+    if [[ $(app_is_installed wekan_main) == "1" ]]; then
236
+        return
237
+    fi
238
+
239
+    if [ ! -d /var/www/wekan ]; then
240
+        mkdir /var/www/wekan
241
+    fi
242
+    if [ -d $WEKAN_DIR ]; then
243
+        rm -rf $WEKAN_DIR
244
+    fi
245
+
246
+    if [ -d /repos/wekan ]; then
247
+        mkdir -p $WEKAN_DIR
248
+        cp -r -p /repos/wekan/. $WEKAN_DIR
249
+        cd $WEKAN_DIR
250
+        git pull
251
+    else
252
+        function_check git_clone
253
+        git_clone $WEKAN_REPO $WEKAN_DIR
254
+    fi
255
+
256
+    if [ ! -d $WEKAN_DIR ]; then
257
+        echo $'Unable to clone wekan repo'
258
+        exit 783251
259
+    fi
260
+
261
+    # an unprivileged user to run as
262
+    useradd -d $WEKAN_DIR/ wekan
263
+    groupadd wekan
264
+
265
+    cd $WEKAN_DIR
266
+    git checkout $WEKAN_COMMIT -b $WEKAN_COMMIT
267
+    set_completion_param "wekan commit" "$WEKAN_COMMIT"
268
+
269
+    chown -R wekan:wekan $WEKAN_DIR
270
+
271
+    WEKAN_ONION_HOSTNAME=$(add_onion_service wekan 80 ${WEKAN_ONION_PORT})
272
+    set_completion_param "wekan onion domain" "$WEKAN_ONION_HOSTNAME"
273
+
274
+    wekan_nginx_site=/etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
275
+    if [[ ${ONION_ONLY} == "no" ]]; then
276
+        function_check nginx_http_redirect
277
+        nginx_http_redirect ${WEKAN_DOMAIN_NAME}
278
+        echo 'server {' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
279
+        echo '    listen 443 ssl;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
280
+        echo '    listen [::]:443 ssl;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
281
+        echo "    root /var/www/${WEKAN_DOMAIN_NAME}/htdocs;" >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
282
+        echo "    server_name ${WEKAN_DOMAIN_NAME};" >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
283
+        echo '    access_log /dev/null;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
284
+        echo "    error_log /dev/null;" >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
285
+        echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
286
+        function_check nginx_ssl
287
+        nginx_ssl ${WEKAN_DOMAIN_NAME}
288
+        function_check nginx_disable_sniffing
289
+        nginx_disable_sniffing ${WEKAN_DOMAIN_NAME}
290
+        echo '    add_header Strict-Transport-Security max-age=0;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
291
+        echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
292
+        echo '    location / {' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
293
+        function_check nginx_limits
294
+        nginx_limits ${WEKAN_DOMAIN_NAME} '15m'
295
+        echo "        proxy_pass http://localhost:$WEKAN_PORT;" >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
296
+        echo '    }' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
297
+        echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
298
+        echo '    fastcgi_buffers 64 4K;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
299
+        echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
300
+        echo '    error_page 403 /core/templates/403.php;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
301
+        echo '    error_page 404 /core/templates/404.php;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
302
+        echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
303
+        echo '    location = /robots.txt {' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
304
+        echo '        allow all;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
305
+        echo '        log_not_found off;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
306
+        echo '        access_log /dev/null;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
307
+        echo '    }' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
308
+        echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
309
+        nginx_keybase ${WEKAN_DOMAIN_NAME}
310
+        echo '}' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
311
+        echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
312
+    else
313
+        echo -n '' > /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
314
+    fi
315
+    echo 'server {' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
316
+    echo "    listen 127.0.0.1:${WEKAN_ONION_PORT} default_server;" >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
317
+    echo "    root /var/www/$WEKAN_DOMAIN_NAME/htdocs;" >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
318
+    echo "    server_name $WEKAN_DOMAIN_NAME;" >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
319
+    echo '    access_log /dev/null;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
320
+    echo "    error_log /dev/null;" >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
321
+    echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
322
+    function_check nginx_disable_sniffing
323
+    nginx_disable_sniffing ${WEKAN_DOMAIN_NAME}
324
+    echo '    add_header Strict-Transport-Security max-age=0;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
325
+    echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
326
+    echo '    location / {' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
327
+    function_check nginx_limits
328
+    nginx_limits ${WEKAN_DOMAIN_NAME} '15m'
329
+    echo "        proxy_pass http://localhost:$WEKAN_PORT;" >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
330
+    echo '    }' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
331
+    echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
332
+    echo '    fastcgi_buffers 64 4K;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
333
+    echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
334
+    echo '    error_page 403 /core/templates/403.php;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
335
+    echo '    error_page 404 /core/templates/404.php;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
336
+    echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
337
+    echo '    location = /robots.txt {' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
338
+    echo '        allow all;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
339
+    echo '        log_not_found off;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
340
+    echo '        access_log /dev/null;' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
341
+    echo '    }' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
342
+    echo '' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
343
+    nginx_keybase ${WEKAN_DOMAIN_NAME}
344
+    echo '}' >> /etc/nginx/sites-available/${WEKAN_DOMAIN_NAME}
345
+
346
+    function_check nginx_ensite
347
+    nginx_ensite wekan
348
+
349
+    install_completed wekan_main
350
+}
351
+
352
+function install_wekan {
353
+    apt-get -qy install build-essential c++ capnproto curl
354
+
355
+    function_check install_nodejs
356
+    install_nodejs wekan
357
+
358
+    install_wekan_main
359
+    install_meteor
360
+
361
+    cd $WEKAN_DIR
362
+
363
+    su -c 'npm install babel-runtime' - wekan
364
+    su -c 'npm install node-gyp' - wekan
365
+    su -c 'npm install node-pre-gyp' - wekan
366
+    su -c 'npm install fibers' - wekan
367
+    su -c 'npm install bcrypt' - wekan
368
+    su -c 'npm install bson' - wekan
369
+    su -c 'npm install es6-promise' - wekan
370
+    su -c 'npm install meteor-node-stubs' - wekan
371
+    su -c 'npm install winston' - wekan
372
+    su -c 'npm install winston-zulip' - wekan
373
+    su -c 'npm install xss' - wekan
374
+
375
+    # Remove any directories from previous installs
376
+    if [ -d $WEKAN_DIR/.meteor ]; then
377
+        rm -rf $WEKAN_DIR/.meteor
378
+    fi
379
+    if [ -d $WEKAN_DIR/app ]; then
380
+        rm -rf $WEKAN_DIR/app
381
+    fi
382
+    if [ -d $WEKAN_DIR/app_build ]; then
383
+        rm -rf $WEKAN_DIR/app_build
384
+    fi
385
+
386
+    # Get additional packages
387
+    mkdir -p $WEKAN_DIR/.meteor/packages
388
+    chown wekan:wekan --recursive $WEKAN_DIR/.meteor
389
+    cd $WEKAN_DIR/.meteor/packages
390
+    if [ ! -d /repos/flowrouter ]; then
391
+        su -c "git clone --depth 1 -b master $FLOW_ROUTER_REPO kadira-flow-router" - wekan
392
+    else
393
+        mkdir kadira-flow-router
394
+        cp -r -p /repos/flowrouter/. kadira-flow-router
395
+        cd kadira-flow-router
396
+        git pull
397
+        cd ..
398
+    fi
399
+    cd kadira-flow-router
400
+    git checkout $FLOW_ROUTER_COMMIT -b $FLOW_ROUTER_COMMIT
401
+    cd ..
402
+    if [ ! -d /repos/meteoruseraccounts ]; then
403
+        su -c "git clone --depth 1 -b master $METEOR_USERACCOUNTS_REPO meteor-useraccounts-core" - wekan
404
+    else
405
+        mkdir meteor-useraccounts-core
406
+        cp -r -p /repos/meteoruseraccounts/. meteor-useraccounts-core
407
+        cd meteor-useraccounts-core
408
+        git pull
409
+        cd ..
410
+    fi
411
+    cd meteor-useraccounts-core
412
+    git checkout $METEOR_USERACCOUNTS_COMMIT -b $METEOR_USERACCOUNTS_COMMIT
413
+    cd ..
414
+    if [ ! -f $WEKAN_DIR/.meteor/packages/meteor-useraccounts-core/package.js ]; then
415
+        echo $"File not found: $WEKAN_DIR/.meteor/packages/meteor-useraccounts-core/package.js"
416
+        exit 7289529
417
+    fi
418
+    sed -i 's/api\.versionsFrom/\/\/api.versionsFrom/' $WEKAN_DIR/.meteor/packages/meteor-useraccounts-core/package.js
419
+    cd $WEKAN_DIR/.meteor
420
+    su -c "$WEKAN_DIR/.meteor/meteor -- help" - wekan
421
+
422
+    # Build app
423
+    if [ ! -d $WEKAN_DIR/app ]; then
424
+        echo $'No app subdirectory found'
425
+        exit 294569
426
+    fi
427
+    cd $WEKAN_DIR/app
428
+    su -c "$WEKAN_DIR/.meteor/meteor add standard-minifier-js" - wekan
429
+    su -c "$WEKAN_DIR/.meteor/meteor npm install" - wekan
430
+    su -c "$WEKAN_DIR/.meteor/meteor build --directory $WEKAN_DIR/app_build" - wekan
431
+    cp $WEKAN_DIR/app/fix-download-unicode/cfs_access-point.txt $WEKAN_DIR/app_build/bundle/programs/server/packages/cfs_access-point.js
432
+    chown wekan:wekan $WEKAN_DIR/app_build/bundle/programs/server/packages/cfs_access-point.js
433
+    sed -i "s|build\/Release\/bson|browser_build\/bson|g" $WEKAN_DIR/app_build/bundle/programs/server/npm/node_modules/meteor/cfs_gridfs/node_modules/mongodb/node_modules/bson/ext/index.js
434
+    if [ ! -d $WEKAN_DIR/app_build/bundle/programs/server/npm/node_modules/meteor/npm-bcrypt ]; then
435
+        echo $"No subdirectory found: $WEKAN_DIR/app_build/bundle/programs/server/npm/node_modules/meteor/npm-bcrypt"
436
+        exit 479832
437
+    fi
438
+    cd $WEKAN_DIR/app_build/bundle/programs/server/npm/node_modules/meteor/npm-bcrypt
439
+    su -c 'rm -rf node_modules/bcrypt' - wekan
440
+    su -c 'npm install bcrypt' - wekan
441
+    cd $WEKAN_DIR/app_build/bundle/programs/server/
442
+    su -c 'npm install' - wekan
443
+    mv $WEKAN_DIR/app_build/bundle ../build
444
+
445
+    if [ ! -f $WEKAN_DIR/build/main.js ]; then
446
+        echo $'main.js not found'
447
+        exit 7828252
448
+    fi
449
+
450
+    # Cleanup
451
+    rm -R $WEKAN_DIR/.meteor
452
+    rm -R $WEKAN_DIR/app
453
+    rm -R $WEKAN_DIR/app_build
454
+
455
+    chown -R wekan:wekan $WEKAN_DIR
456
+
457
+    function_check install_mariadb
458
+    install_mariadb
459
+
460
+    function_check get_mariadb_password
461
+    get_mariadb_password
462
+
463
+    function_check wekan_create_database
464
+    wekan_create_database
465
+
466
+    # daemon
467
+    echo '[Unit]' > /etc/systemd/system/wekan.service
468
+    echo 'Description=Wekan' >> /etc/systemd/system/wekan.service
469
+    echo 'After=syslog.target' >> /etc/systemd/system/wekan.service
470
+    echo 'After=network.target' >> /etc/systemd/system/wekan.service
471
+    echo '' >> /etc/systemd/system/wekan.service
472
+    echo '[Service]' >> /etc/systemd/system/wekan.service
473
+    echo 'User=wekan' >> /etc/systemd/system/wekan.service
474
+    echo 'Group=wekan' >> /etc/systemd/system/wekan.service
475
+    echo "WorkingDirectory=$WEKAN_DIR" >> /etc/systemd/system/wekan.service
476
+    echo "ExecStart=/usr/local/bin/node $WEKAN_DIR/build/main.js" >> /etc/systemd/system/wekan.service
477
+    echo 'Environment=PATH=/usr/bin:/usr/local/bin' >> /etc/systemd/system/wekan.service
478
+    echo 'Environment=NODE_ENV=production' >> /etc/systemd/system/wekan.service
479
+    echo 'Restart=on-failure' >> /etc/systemd/system/wekan.service
480
+    echo '' >> /etc/systemd/system/wekan.service
481
+    echo '[Install]' >> /etc/systemd/system/wekan.service
482
+    echo 'WantedBy=multi-user.target' >> /etc/systemd/system/wekan.service
483
+    systemctl enable wekan.service
484
+    systemctl daemon-reload
485
+    systemctl start wekan.service
486
+
487
+    systemctl restart nginx
488
+
489
+    set_completion_param "wekan domain" "$WEKAN_DOMAIN_NAME"
490
+
491
+    APP_INSTALLED=1
492
+}
493
+
494
+# NOTE: deliberately there is no "exit 0"

+ 5
- 0
src/freedombone-image-customise Parādīt failu

@@ -1274,6 +1274,11 @@ function image_preinstall_repos {
1274 1274
     git clone $TOXID_REPO $rootdir/repos/toxid
1275 1275
     git clone $TOXIC_REPO $rootdir/repos/toxic
1276 1276
     git clone $TURTL_REPO $rootdir/repos/turtl
1277
+    git clone $KANBOARD_REPO $rootdir/repos/kanboard
1278
+    #git clone $WEKAN_REPO $rootdir/repos/wekan
1279
+    #git clone $FLOW_ROUTER_REPO $rootdir/repos/flowrouter
1280
+    #git clone $METEOR_USERACCOUNTS_REPO $rootdir/repos/meteoruseraccounts
1281
+    #git clone $METEOR_REPO $rootdir/repos/meteor
1277 1282
     #git clone $ZERONET_REPO $rootdir/repos/zeronet
1278 1283
     #git clone $QTOX_REPO $rootdir/repos/qtox
1279 1284
 }

+ 220
- 0
src/freedombone-utils-meteor Parādīt failu

@@ -0,0 +1,220 @@
1
+#!/bin/bash
2
+#
3
+# .---.                  .              .
4
+# |                      |              |
5
+# |--- .--. .-.  .-.  .-.|  .-. .--.--. |.-.  .-. .--.  .-.
6
+# |    |   (.-' (.-' (   | (   )|  |  | |   )(   )|  | (.-'
7
+# '    '     --'  --'  -' -  -' '  '   -' -'   -' '   -  --'
8
+#
9
+#                    Freedom in the Cloud
10
+#
11
+# Functions for installing meteor
12
+# See meteor.com
13
+#
14
+# License
15
+# =======
16
+#
17
+# Copyright (C) 2017 Bob Mottram <bob@freedombone.net>
18
+#
19
+# This program is free software: you can redistribute it and/or modify
20
+# it under the terms of the GNU Affero General Public License as published by
21
+# the Free Software Foundation, either version 3 of the License, or
22
+# (at your option) any later version.
23
+#
24
+# This program is distributed in the hope that it will be useful,
25
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
26
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
+# GNU Affero General Public License for more details.
28
+#
29
+# You should have received a copy of the GNU Affero General Public License
30
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
31
+
32
+METEOR_RELEASE='1.4.4.1'
33
+METEOR_REPO="https://github.com/meteor/meteor"
34
+METEOR_COMMIT='b52c6587d7542c0f27481a3bee8c65be06068ac1'
35
+METEOR_USERACCOUNTS_REPO="git://github.com/meteor-useraccounts/core.git"
36
+METEOR_USERACCOUNTS_COMMIT='2e8986813b51f321f908d2f6211f6f81f76cd627'
37
+
38
+function meteor_cleanUp {
39
+    rm -rf "$TARBALL_FILE"
40
+    rm -rf "$INSTALL_TMPDIR"
41
+}
42
+
43
+function install_meteor_script {
44
+    meteor_dir=$1
45
+
46
+    if [ ! $meteor_dir ]; then
47
+        echo $'No meteor install directory specified'
48
+        exit 692025
49
+    fi
50
+
51
+    if [ ! -d $meteor_dir ]; then
52
+        echo $'Meteor install directory not found'
53
+        exit 845382
54
+    fi
55
+
56
+    if [[ "$(arch)" == "arm"* ]]; then
57
+        echo 'meteor does not support ARM'
58
+        exit 8362952
59
+    fi
60
+    if [[ "$(arch)" == "i386" || "$(arch)" == "x86_32" ]]; then
61
+        PLATFORM="os.linux.x86_32"
62
+    else
63
+        PLATFORM="os.linux.x86_64"
64
+    fi
65
+
66
+    RELEASE="$METEOR_RELEASE"
67
+
68
+    DIR_PREFIX="/usr/local"
69
+
70
+    TARBALL_URL="$https://meteorinstall-4168.kxcdn.com/packages-bootstrap/${RELEASE}/meteor-bootstrap-${PLATFORM}.tar.gz"
71
+    INSTALL_TMPDIR="$meteor_dir/.meteor-install-tmp"
72
+    TARBALL_FILE="$meteor_dir/.meteor-tarball-tmp"
73
+
74
+    # Remove temporary files now in case they exist.
75
+    meteor_cleanUp
76
+
77
+    if [ -d $INSTALL_TMPDIR ]; then
78
+        rm -rf $INSTALL_TMPDIR
79
+    fi
80
+    mkdir "$INSTALL_TMPDIR"
81
+
82
+    if [ ! -f ${TARBALL_FILE} ]; then
83
+        echo "Downloading Meteor distribution"
84
+        # keep trying to curl the file until it works (resuming where possible)
85
+        MAX_ATTEMPTS=10
86
+        RETRY_DELAY_SECS=5
87
+        set +e
88
+        ATTEMPTS=0
89
+        while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]
90
+        do
91
+            ATTEMPTS=$((ATTEMPTS + 1))
92
+
93
+            curl --progress-bar --fail --continue-at - \
94
+                 "$TARBALL_URL" --output "$TARBALL_FILE"
95
+
96
+            if [ $? -eq 0 ]
97
+            then
98
+                break
99
+            fi
100
+
101
+            echo "Retrying download in $RETRY_DELAY_SECS seconds..."
102
+            sleep $RETRY_DELAY_SECS
103
+        done
104
+    fi
105
+
106
+    if [ ! -f ${TARBALL_FILE} ]; then
107
+        echo $'meteor tarball could not be downloaded'
108
+        exit 7272452
109
+    fi
110
+
111
+    tar -xzf "$TARBALL_FILE" -C "$INSTALL_TMPDIR" -o
112
+
113
+    if [ ! -f ${INSTALL_TMPDIR}/.meteor/meteor ]; then
114
+        echo $'tarball not extracted'
115
+        exit 693252
116
+    fi
117
+
118
+    mv "${INSTALL_TMPDIR}/.meteor" "$meteor_dir"
119
+
120
+    meteor_cleanUp
121
+
122
+    echo ''
123
+    echo "Meteor ${RELEASE} has been installed in $meteor_dir/.meteor"
124
+
125
+    METEOR_SYMLINK_TARGET="$(readlink "$meteor_dir/.meteor/meteor")"
126
+    METEOR_TOOL_DIRECTORY="$(dirname "$METEOR_SYMLINK_TARGET")"
127
+    LAUNCHER="$meteor_dir/.meteor/$METEOR_TOOL_DIRECTORY/scripts/admin/launch-meteor"
128
+
129
+    if cp "$LAUNCHER" "$DIR_PREFIX/bin/meteor" >/dev/null 2>&1; then
130
+        echo "Writing a launcher script to $DIR_PREFIX/bin/meteor for your convenience."
131
+        cat <<"EOF"
132
+
133
+To get started fast:
134
+
135
+  $ meteor create ~/my_cool_app
136
+  $ cd ~/my_cool_app
137
+  $ meteor
138
+
139
+Or see the docs at:
140
+
141
+  docs.meteor.com
142
+
143
+EOF
144
+    elif type sudo >/dev/null 2>&1; then
145
+        echo "Writing a launcher script to $DIR_PREFIX/bin/meteor for your convenience."
146
+        echo "This may prompt for your password."
147
+
148
+        # New macs (10.9+) don't ship with /usr/local, however it is still in
149
+        # the default PATH. We still install there, we just need to create the
150
+        # directory first.
151
+        # XXX this means that we can run sudo too many times. we should never
152
+        #     run it more than once if it fails the first time
153
+        if [ ! -d "$DIR_PREFIX/bin" ] ; then
154
+            sudo mkdir -m 755 "$DIR_PREFIX" || true
155
+            sudo mkdir -m 755 "$DIR_PREFIX/bin" || true
156
+        fi
157
+
158
+        if sudo cp "$LAUNCHER" "$DIR_PREFIX/bin/meteor"; then
159
+            cat <<"EOF"
160
+
161
+To get started fast:
162
+
163
+  $ meteor create ~/my_cool_app
164
+  $ cd ~/my_cool_app
165
+  $ meteor
166
+
167
+Or see the docs at:
168
+
169
+  docs.meteor.com
170
+
171
+EOF
172
+        else
173
+            cat <<EOF
174
+
175
+Couldn't write the launcher script. Please either:
176
+
177
+  (1) Run the following as root:
178
+        cp "$LAUNCHER" /usr/bin/meteor
179
+  (2) Add "\$meteor_dir/.meteor" to your path, or
180
+  (3) Rerun this command to try again.
181
+
182
+Then to get started, take a look at 'meteor --help' or see the docs at
183
+docs.meteor.com.
184
+EOF
185
+        fi
186
+    else
187
+        cat <<EOF
188
+
189
+Now you need to do one of the following:
190
+
191
+  (1) Add "\$meteor_dir/.meteor" to your path, or
192
+  (2) Run this command as root:
193
+        cp "$LAUNCHER" /usr/bin/meteor
194
+
195
+Then to get started, take a look at 'meteor --help' or see the docs at
196
+docs.meteor.com.
197
+EOF
198
+    fi
199
+
200
+}
201
+
202
+function install_meteor {
203
+    apt-get -yq install curl
204
+    if [ ! -d $INSTALL_DIR/meteor ]; then
205
+        mkdir $INSTALL_DIR/meteor
206
+    fi
207
+    cd $INSTALL_DIR/meteor
208
+    install_meteor_script
209
+}
210
+
211
+function remove_meteor {
212
+    if [ -f /usr/local/bin/meteor ]; then
213
+        rm /usr/local/bin/meteor
214
+    fi
215
+    if [ -f /usr/bin/meteor ]; then
216
+        rm /usr/bin/meteor
217
+    fi
218
+}
219
+
220
+# NOTE: deliberately no exit 0

+ 16
- 0
src/freedombone-utils-web Parādīt failu

@@ -917,4 +917,20 @@ function create_default_web_site {
917 917
     fi
918 918
 }
919 919
 
920
+function install_composer {
921
+    # curl -sS https://getcomposer.org/installer | php
922
+    if [ -f ~/${PROJECT_NAME}/image_build/composer_install ]; then
923
+        cat ~/${PROJECT_NAME}/image_build/composer_install | php
924
+    else
925
+        if [ -f /home/$MY_USERNAME/${PROJECT_NAME}/image_build/composer_install ]; then
926
+            cat /home/$MY_USERNAME/${PROJECT_NAME}/image_build/composer_install | php
927
+        fi
928
+    fi
929
+    php composer.phar install
930
+    if [ ! "$?" = "0" ]; then
931
+        echo $'Unable to run composer install'
932
+        exit 7252198
933
+    fi
934
+}
935
+
920 936
 # NOTE: deliberately no exit 0

+ 12
- 4
website/EN/app_cryptpad.html Parādīt failu

@@ -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-05-28 Sun 11:33 -->
6
+<!-- 2017-07-27 Thu 15:16 -->
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></title>
@@ -248,6 +248,14 @@ for the JavaScript code in this tag.
248 248
 <h1>CryptPad</h1>
249 249
 </center>
250 250
 
251
+<div class="org-center">
252
+
253
+<div class="figure">
254
+<p><img src="images/cryptpad.jpg" alt="cryptpad.jpg" />
255
+</p>
256
+</div>
257
+</div>
258
+
251 259
 <p>
252 260
 This is similar to <a href="./app_etherpad.html">EtherPad</a> but with better security and more document types which can be collaboratively edited in real time. It includes not just text editing but also creating presentations, voting and editing source code.
253 261
 </p>
@@ -264,9 +272,9 @@ Enabling someone to edit a document is as simple as sending them the URL via a c
264 272
 Documents are stored locally within the browser of each user and the server just acts as a coordinator. No documents are stored on the server.
265 273
 </p>
266 274
 
267
-<div id="outline-container-orgd443efe" class="outline-2">
268
-<h2 id="orgd443efe">Installation</h2>
269
-<div class="outline-text-2" id="text-orgd443efe">
275
+<div id="outline-container-orgf7a5294" class="outline-2">
276
+<h2 id="orgf7a5294">Installation</h2>
277
+<div class="outline-text-2" id="text-orgf7a5294">
270 278
 <p>
271 279
 Log into your system with:
272 280
 </p>

+ 323
- 0
website/EN/app_kanboard.html Parādīt failu

@@ -0,0 +1,323 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
5
+<head>
6
+<!-- 2017-07-25 Tue 23:23 -->
7
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
8
+<meta name="viewport" content="width=device-width, initial-scale=1" />
9
+<title></title>
10
+<meta name="generator" content="Org mode" />
11
+<meta name="author" content="Bob Mottram" />
12
+<meta name="description" content="How to use KanBoard"
13
+ />
14
+<meta name="keywords" content="freedombone, kanboard" />
15
+<style type="text/css">
16
+ <!--/*--><![CDATA[/*><!--*/
17
+  .title  { text-align: center;
18
+             margin-bottom: .2em; }
19
+  .subtitle { text-align: center;
20
+              font-size: medium;
21
+              font-weight: bold;
22
+              margin-top:0; }
23
+  .todo   { font-family: monospace; color: red; }
24
+  .done   { font-family: monospace; color: green; }
25
+  .priority { font-family: monospace; color: orange; }
26
+  .tag    { background-color: #eee; font-family: monospace;
27
+            padding: 2px; font-size: 80%; font-weight: normal; }
28
+  .timestamp { color: #bebebe; }
29
+  .timestamp-kwd { color: #5f9ea0; }
30
+  .org-right  { margin-left: auto; margin-right: 0px;  text-align: right; }
31
+  .org-left   { margin-left: 0px;  margin-right: auto; text-align: left; }
32
+  .org-center { margin-left: auto; margin-right: auto; text-align: center; }
33
+  .underline { text-decoration: underline; }
34
+  #postamble p, #preamble p { font-size: 90%; margin: .2em; }
35
+  p.verse { margin-left: 3%; }
36
+  pre {
37
+    border: 1px solid #ccc;
38
+    box-shadow: 3px 3px 3px #eee;
39
+    padding: 8pt;
40
+    font-family: monospace;
41
+    overflow: auto;
42
+    margin: 1.2em;
43
+  }
44
+  pre.src {
45
+    position: relative;
46
+    overflow: visible;
47
+    padding-top: 1.2em;
48
+  }
49
+  pre.src:before {
50
+    display: none;
51
+    position: absolute;
52
+    background-color: white;
53
+    top: -10px;
54
+    right: 10px;
55
+    padding: 3px;
56
+    border: 1px solid black;
57
+  }
58
+  pre.src:hover:before { display: inline;}
59
+  /* Languages per Org manual */
60
+  pre.src-asymptote:before { content: 'Asymptote'; }
61
+  pre.src-awk:before { content: 'Awk'; }
62
+  pre.src-C:before { content: 'C'; }
63
+  /* pre.src-C++ doesn't work in CSS */
64
+  pre.src-clojure:before { content: 'Clojure'; }
65
+  pre.src-css:before { content: 'CSS'; }
66
+  pre.src-D:before { content: 'D'; }
67
+  pre.src-ditaa:before { content: 'ditaa'; }
68
+  pre.src-dot:before { content: 'Graphviz'; }
69
+  pre.src-calc:before { content: 'Emacs Calc'; }
70
+  pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
71
+  pre.src-fortran:before { content: 'Fortran'; }
72
+  pre.src-gnuplot:before { content: 'gnuplot'; }
73
+  pre.src-haskell:before { content: 'Haskell'; }
74
+  pre.src-hledger:before { content: 'hledger'; }
75
+  pre.src-java:before { content: 'Java'; }
76
+  pre.src-js:before { content: 'Javascript'; }
77
+  pre.src-latex:before { content: 'LaTeX'; }
78
+  pre.src-ledger:before { content: 'Ledger'; }
79
+  pre.src-lisp:before { content: 'Lisp'; }
80
+  pre.src-lilypond:before { content: 'Lilypond'; }
81
+  pre.src-lua:before { content: 'Lua'; }
82
+  pre.src-matlab:before { content: 'MATLAB'; }
83
+  pre.src-mscgen:before { content: 'Mscgen'; }
84
+  pre.src-ocaml:before { content: 'Objective Caml'; }
85
+  pre.src-octave:before { content: 'Octave'; }
86
+  pre.src-org:before { content: 'Org mode'; }
87
+  pre.src-oz:before { content: 'OZ'; }
88
+  pre.src-plantuml:before { content: 'Plantuml'; }
89
+  pre.src-processing:before { content: 'Processing.js'; }
90
+  pre.src-python:before { content: 'Python'; }
91
+  pre.src-R:before { content: 'R'; }
92
+  pre.src-ruby:before { content: 'Ruby'; }
93
+  pre.src-sass:before { content: 'Sass'; }
94
+  pre.src-scheme:before { content: 'Scheme'; }
95
+  pre.src-screen:before { content: 'Gnu Screen'; }
96
+  pre.src-sed:before { content: 'Sed'; }
97
+  pre.src-sh:before { content: 'shell'; }
98
+  pre.src-sql:before { content: 'SQL'; }
99
+  pre.src-sqlite:before { content: 'SQLite'; }
100
+  /* additional languages in org.el's org-babel-load-languages alist */
101
+  pre.src-forth:before { content: 'Forth'; }
102
+  pre.src-io:before { content: 'IO'; }
103
+  pre.src-J:before { content: 'J'; }
104
+  pre.src-makefile:before { content: 'Makefile'; }
105
+  pre.src-maxima:before { content: 'Maxima'; }
106
+  pre.src-perl:before { content: 'Perl'; }
107
+  pre.src-picolisp:before { content: 'Pico Lisp'; }
108
+  pre.src-scala:before { content: 'Scala'; }
109
+  pre.src-shell:before { content: 'Shell Script'; }
110
+  pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
111
+  /* additional language identifiers per "defun org-babel-execute"
112
+       in ob-*.el */
113
+  pre.src-cpp:before  { content: 'C++'; }
114
+  pre.src-abc:before  { content: 'ABC'; }
115
+  pre.src-coq:before  { content: 'Coq'; }
116
+  pre.src-groovy:before  { content: 'Groovy'; }
117
+  /* additional language identifiers from org-babel-shell-names in
118
+     ob-shell.el: ob-shell is the only babel language using a lambda to put
119
+     the execution function name together. */
120
+  pre.src-bash:before  { content: 'bash'; }
121
+  pre.src-csh:before  { content: 'csh'; }
122
+  pre.src-ash:before  { content: 'ash'; }
123
+  pre.src-dash:before  { content: 'dash'; }
124
+  pre.src-ksh:before  { content: 'ksh'; }
125
+  pre.src-mksh:before  { content: 'mksh'; }
126
+  pre.src-posh:before  { content: 'posh'; }
127
+  /* Additional Emacs modes also supported by the LaTeX listings package */
128
+  pre.src-ada:before { content: 'Ada'; }
129
+  pre.src-asm:before { content: 'Assembler'; }
130
+  pre.src-caml:before { content: 'Caml'; }
131
+  pre.src-delphi:before { content: 'Delphi'; }
132
+  pre.src-html:before { content: 'HTML'; }
133
+  pre.src-idl:before { content: 'IDL'; }
134
+  pre.src-mercury:before { content: 'Mercury'; }
135
+  pre.src-metapost:before { content: 'MetaPost'; }
136
+  pre.src-modula-2:before { content: 'Modula-2'; }
137
+  pre.src-pascal:before { content: 'Pascal'; }
138
+  pre.src-ps:before { content: 'PostScript'; }
139
+  pre.src-prolog:before { content: 'Prolog'; }
140
+  pre.src-simula:before { content: 'Simula'; }
141
+  pre.src-tcl:before { content: 'tcl'; }
142
+  pre.src-tex:before { content: 'TeX'; }
143
+  pre.src-plain-tex:before { content: 'Plain TeX'; }
144
+  pre.src-verilog:before { content: 'Verilog'; }
145
+  pre.src-vhdl:before { content: 'VHDL'; }
146
+  pre.src-xml:before { content: 'XML'; }
147
+  pre.src-nxml:before { content: 'XML'; }
148
+  /* add a generic configuration mode; LaTeX export needs an additional
149
+     (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
150
+  pre.src-conf:before { content: 'Configuration File'; }
151
+
152
+  table { border-collapse:collapse; }
153
+  caption.t-above { caption-side: top; }
154
+  caption.t-bottom { caption-side: bottom; }
155
+  td, th { vertical-align:top;  }
156
+  th.org-right  { text-align: center;  }
157
+  th.org-left   { text-align: center;   }
158
+  th.org-center { text-align: center; }
159
+  td.org-right  { text-align: right;  }
160
+  td.org-left   { text-align: left;   }
161
+  td.org-center { text-align: center; }
162
+  dt { font-weight: bold; }
163
+  .footpara { display: inline; }
164
+  .footdef  { margin-bottom: 1em; }
165
+  .figure { padding: 1em; }
166
+  .figure p { text-align: center; }
167
+  .inlinetask {
168
+    padding: 10px;
169
+    border: 2px solid gray;
170
+    margin: 10px;
171
+    background: #ffffcc;
172
+  }
173
+  #org-div-home-and-up
174
+   { text-align: right; font-size: 70%; white-space: nowrap; }
175
+  textarea { overflow-x: auto; }
176
+  .linenr { font-size: smaller }
177
+  .code-highlighted { background-color: #ffff00; }
178
+  .org-info-js_info-navigation { border-style: none; }
179
+  #org-info-js_console-label
180
+    { font-size: 10px; font-weight: bold; white-space: nowrap; }
181
+  .org-info-js_search-highlight
182
+    { background-color: #ffff00; color: #000000; font-weight: bold; }
183
+  .org-svg { width: 90%; }
184
+  /*]]>*/-->
185
+</style>
186
+<link rel="stylesheet" type="text/css" href="freedombone.css" />
187
+<script type="text/javascript">
188
+/*
189
+@licstart  The following is the entire license notice for the
190
+JavaScript code in this tag.
191
+
192
+Copyright (C) 2012-2017 Free Software Foundation, Inc.
193
+
194
+The JavaScript code in this tag is free software: you can
195
+redistribute it and/or modify it under the terms of the GNU
196
+General Public License (GNU GPL) as published by the Free Software
197
+Foundation, either version 3 of the License, or (at your option)
198
+any later version.  The code is distributed WITHOUT ANY WARRANTY;
199
+without even the implied warranty of MERCHANTABILITY or FITNESS
200
+FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
201
+
202
+As additional permission under GNU GPL version 3 section 7, you
203
+may distribute non-source (e.g., minimized or compacted) forms of
204
+that code without the copy of the GNU GPL normally required by
205
+section 4, provided you include this license notice and a URL
206
+through which recipients can access the Corresponding Source.
207
+
208
+
209
+@licend  The above is the entire license notice
210
+for the JavaScript code in this tag.
211
+*/
212
+<!--/*--><![CDATA[/*><!--*/
213
+ function CodeHighlightOn(elem, id)
214
+ {
215
+   var target = document.getElementById(id);
216
+   if(null != target) {
217
+     elem.cacheClassElem = elem.className;
218
+     elem.cacheClassTarget = target.className;
219
+     target.className = "code-highlighted";
220
+     elem.className   = "code-highlighted";
221
+   }
222
+ }
223
+ function CodeHighlightOff(elem, id)
224
+ {
225
+   var target = document.getElementById(id);
226
+   if(elem.cacheClassElem)
227
+     elem.className = elem.cacheClassElem;
228
+   if(elem.cacheClassTarget)
229
+     target.className = elem.cacheClassTarget;
230
+ }
231
+/*]]>*///-->
232
+</script>
233
+</head>
234
+<body>
235
+<div id="preamble" class="status">
236
+<a name="top" id="top"></a>
237
+</div>
238
+<div id="content">
239
+<div class="org-center">
240
+
241
+<div class="figure">
242
+<p><img src="images/logo.png" alt="logo.png" />
243
+</p>
244
+</div>
245
+</div>
246
+
247
+<center>
248
+<h1>KanBoard</h1>
249
+</center>
250
+
251
+<p>
252
+Kanbans are one way of managing projects. They're traditionally used in businesses but can also be useful for personal TODO lists or within open source or DIY projects. If you have a list of things which need to be done and want to keep track of progress then this provides a way to do that.
253
+</p>
254
+
255
+<div id="outline-container-orgfd145f9" class="outline-2">
256
+<h2 id="orgfd145f9">Installation</h2>
257
+<div class="outline-text-2" id="text-orgfd145f9">
258
+<p>
259
+Log into your system with:
260
+</p>
261
+
262
+<div class="org-src-container">
263
+<pre><code class="src src-bash">ssh myusername@mydomain -p 2222
264
+</code></pre>
265
+</div>
266
+
267
+<p>
268
+Using cursor keys, space bar and Enter key select <b>Administrator controls</b> and type in your password.
269
+</p>
270
+
271
+<p>
272
+Select <b>Add/Remove Apps</b> then <b>kanboard</b>. You will then be asked for a domain name and if you are using FreeDNS also the code for the domain which can be found under <b>Dynamic DNS</b> on the FreeDNS site (the random string from "<i>quick cron example</i>" which appears after <i>update.php?</i> and before <i>&gt;&gt;</i>). For more details on obtaining a domain and making it accessible via dynamic DNS see the <a href="./faq.html">FAQ</a>. Typically the domain name you use will be a subdomain, such as <i>kanban.mydomainname.net</i>. It will need to be a domain which you have bought somewhere and own and not one of the FreeDNS subdomains, otherwise you won't be able to get a SSL/TLS certificate for it.
273
+</p>
274
+
275
+<p>
276
+After the install has completed go to <b>Security settings</b> and select <b>Create a new Let's Encrypt certificate</b> and enter the domain name that you are using for KanBoard. If you're using the "onion only" version of the system then you don't need to do this. If the certificate is obtained successfully then you will see a congratulations message.
277
+</p>
278
+</div>
279
+</div>
280
+
281
+<div id="outline-container-org2e3435d" class="outline-2">
282
+<h2 id="org2e3435d">Initial setup</h2>
283
+<div class="outline-text-2" id="text-org2e3435d">
284
+<p>
285
+If you have just obtained a Lets Encrypt certificate as above then go to <b>About</b> on the administrator control panel and you should see your KanBoard domain listed there along with an onion address. You can then navigate to your site in a browser.
286
+</p>
287
+
288
+<p>
289
+The default login is username "admin" and password "admin". Obviously the first thing you'll need to do is log in and change the password, which can be done by going to "My Profile" on the drop down list on the right hand side.
290
+</p>
291
+
292
+<p>
293
+For more details of how to use KanBoard see the <a href="https://kanboard.net/documentation">documentation here</a>.
294
+</p>
295
+</div>
296
+</div>
297
+</div>
298
+<div id="postamble" class="status">
299
+
300
+<style type="text/css">
301
+.back-to-top {
302
+    position: fixed;
303
+    bottom: 2em;
304
+    right: 0px;
305
+    text-decoration: none;
306
+    color: #000000;
307
+    background-color: rgba(235, 235, 235, 0.80);
308
+    font-size: 12px;
309
+    padding: 1em;
310
+    display: none;
311
+}
312
+
313
+.back-to-top:hover {
314
+    background-color: rgba(135, 135, 135, 0.50);
315
+}
316
+</style>
317
+
318
+<div class="back-to-top">
319
+<a href="#top">Back to top</a> | <a href="mailto:bob@freedombone.net">E-mail me</a>
320
+</div>
321
+</div>
322
+</body>
323
+</html>

+ 109
- 97
website/EN/apps.html Parādīt failu

@@ -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-06-25 Sun 21:57 -->
6
+<!-- 2017-07-25 Tue 23:25 -->
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></title>
@@ -264,9 +264,9 @@ The base install of the system just contains an email server and Mutt client, bu
264 264
 </div>
265 265
 </div>
266 266
 
267
-<div id="outline-container-org63f1146" class="outline-2">
268
-<h2 id="org63f1146">CryptPad</h2>
269
-<div class="outline-text-2" id="text-org63f1146">
267
+<div id="outline-container-org9a19246" class="outline-2">
268
+<h2 id="org9a19246">CryptPad</h2>
269
+<div class="outline-text-2" id="text-org9a19246">
270 270
 <p>
271 271
 Collaborate on editing documents, presentations and source code, or vote on things. All with a good level of security.
272 272
 </p>
@@ -276,9 +276,9 @@ Collaborate on editing documents, presentations and source code, or vote on thin
276 276
 </p>
277 277
 </div>
278 278
 </div>
279
-<div id="outline-container-orgf372cd2" class="outline-2">
280
-<h2 id="orgf372cd2">DLNA</h2>
281
-<div class="outline-text-2" id="text-orgf372cd2">
279
+<div id="outline-container-orgaf887a3" class="outline-2">
280
+<h2 id="orgaf887a3">DLNA</h2>
281
+<div class="outline-text-2" id="text-orgaf887a3">
282 282
 <p>
283 283
 Enables you to use the system as a music server which any DLNA compatible devices can connect to within your home network.
284 284
 </p>
@@ -288,9 +288,9 @@ Enables you to use the system as a music server which any DLNA compatible device
288 288
 </p>
289 289
 </div>
290 290
 </div>
291
-<div id="outline-container-orge69d870" class="outline-2">
292
-<h2 id="orge69d870">Dokuwiki</h2>
293
-<div class="outline-text-2" id="text-orge69d870">
291
+<div id="outline-container-org24b3d95" class="outline-2">
292
+<h2 id="org24b3d95">Dokuwiki</h2>
293
+<div class="outline-text-2" id="text-org24b3d95">
294 294
 <p>
295 295
 A databaseless wiki system.
296 296
 </p>
@@ -300,9 +300,9 @@ A databaseless wiki system.
300 300
 </p>
301 301
 </div>
302 302
 </div>
303
-<div id="outline-container-org748292e" class="outline-2">
304
-<h2 id="org748292e">Emacs</h2>
305
-<div class="outline-text-2" id="text-org748292e">
303
+<div id="outline-container-orga7568ea" class="outline-2">
304
+<h2 id="orga7568ea">Emacs</h2>
305
+<div class="outline-text-2" id="text-orga7568ea">
306 306
 <p>
307 307
 If you use the Mutt client to read your email then this will set it up to use emacs for composing new mail.
308 308
 </p>
@@ -312,9 +312,9 @@ If you use the Mutt client to read your email then this will set it up to use em
312 312
 </p>
313 313
 </div>
314 314
 </div>
315
-<div id="outline-container-org9e62d1f" class="outline-2">
316
-<h2 id="org9e62d1f">Etherpad</h2>
317
-<div class="outline-text-2" id="text-org9e62d1f">
315
+<div id="outline-container-org3d4300f" class="outline-2">
316
+<h2 id="org3d4300f">Etherpad</h2>
317
+<div class="outline-text-2" id="text-org3d4300f">
318 318
 <p>
319 319
 Collaborate on creating documents in real time. Maybe you're planning a holiday with other family members or creating documentation for a Free Software project along with other volunteers. Etherpad is hard to beat for simplicity and speed. Only users of the system will be able to access it.
320 320
 </p>
@@ -324,9 +324,9 @@ Collaborate on creating documents in real time. Maybe you're planning a holiday
324 324
 </p>
325 325
 </div>
326 326
 </div>
327
-<div id="outline-container-org8eb5191" class="outline-2">
328
-<h2 id="org8eb5191">Friendica</h2>
329
-<div class="outline-text-2" id="text-org8eb5191">
327
+<div id="outline-container-org91f769f" class="outline-2">
328
+<h2 id="org91f769f">Friendica</h2>
329
+<div class="outline-text-2" id="text-org91f769f">
330 330
 <p>
331 331
 Federated social network system.
332 332
 </p>
@@ -336,9 +336,9 @@ Federated social network system.
336 336
 </p>
337 337
 </div>
338 338
 </div>
339
-<div id="outline-container-orge13ef3e" class="outline-2">
340
-<h2 id="orge13ef3e">Ghost</h2>
341
-<div class="outline-text-2" id="text-orge13ef3e">
339
+<div id="outline-container-org6266e6b" class="outline-2">
340
+<h2 id="org6266e6b">Ghost</h2>
341
+<div class="outline-text-2" id="text-org6266e6b">
342 342
 <p>
343 343
 Modern looking blogging system.
344 344
 </p>
@@ -348,9 +348,9 @@ Modern looking blogging system.
348 348
 </p>
349 349
 </div>
350 350
 </div>
351
-<div id="outline-container-org18ba256" class="outline-2">
352
-<h2 id="org18ba256">GNU Social</h2>
353
-<div class="outline-text-2" id="text-org18ba256">
351
+<div id="outline-container-orge7307c0" class="outline-2">
352
+<h2 id="orge7307c0">GNU Social</h2>
353
+<div class="outline-text-2" id="text-orge7307c0">
354 354
 <p>
355 355
 Federated social network. You can "<i>remote follow</i>" other users within the GNU Social federation.
356 356
 </p>
@@ -360,9 +360,9 @@ Federated social network. You can "<i>remote follow</i>" other users within the
360 360
 </p>
361 361
 </div>
362 362
 </div>
363
-<div id="outline-container-orgbf05b19" class="outline-2">
364
-<h2 id="orgbf05b19">Gogs</h2>
365
-<div class="outline-text-2" id="text-orgbf05b19">
363
+<div id="outline-container-org42d8a6c" class="outline-2">
364
+<h2 id="org42d8a6c">Gogs</h2>
365
+<div class="outline-text-2" id="text-org42d8a6c">
366 366
 <p>
367 367
 Lightweight git project hosting system. You can mirror projects from Github, or if Github turns evil then just host your own projects while retaining the familiar <i>fork-and-pull</i> workflow. If you can use Github then you can also use Gogs.
368 368
 </p>
@@ -372,9 +372,9 @@ Lightweight git project hosting system. You can mirror projects from Github, or
372 372
 </p>
373 373
 </div>
374 374
 </div>
375
-<div id="outline-container-org14e55c0" class="outline-2">
376
-<h2 id="org14e55c0">HTMLy</h2>
377
-<div class="outline-text-2" id="text-org14e55c0">
375
+<div id="outline-container-org21d5b80" class="outline-2">
376
+<h2 id="org21d5b80">HTMLy</h2>
377
+<div class="outline-text-2" id="text-org21d5b80">
378 378
 <p>
379 379
 Databaseless blogging system. Quite simple and with a markdown-like format.
380 380
 </p>
@@ -384,9 +384,9 @@ Databaseless blogging system. Quite simple and with a markdown-like format.
384 384
 </p>
385 385
 </div>
386 386
 </div>
387
-<div id="outline-container-org4db6ae4" class="outline-2">
388
-<h2 id="org4db6ae4">Hubzilla</h2>
389
-<div class="outline-text-2" id="text-org4db6ae4">
387
+<div id="outline-container-org47d8fc7" class="outline-2">
388
+<h2 id="org47d8fc7">Hubzilla</h2>
389
+<div class="outline-text-2" id="text-org47d8fc7">
390 390
 <p>
391 391
 Web publishing platform with social network like features and good privacy controls so that it's possible to specify who can see which content. Includes photo albums, calendar, wiki and file storage.
392 392
 </p>
@@ -396,9 +396,9 @@ Web publishing platform with social network like features and good privacy contr
396 396
 </p>
397 397
 </div>
398 398
 </div>
399
-<div id="outline-container-org7fae7fd" class="outline-2">
400
-<h2 id="org7fae7fd">IRC Server (ngirc)</h2>
401
-<div class="outline-text-2" id="text-org7fae7fd">
399
+<div id="outline-container-org71113c6" class="outline-2">
400
+<h2 id="org71113c6">IRC Server (ngirc)</h2>
401
+<div class="outline-text-2" id="text-org71113c6">
402 402
 <p>
403 403
 Run your own IRC chat channel which can be secured with a password and accessible via an onion address. A bouncer is included so that you can receive messages sent while you were offline. Works with Hexchat and other popular clients.
404 404
 </p>
@@ -408,18 +408,30 @@ Run your own IRC chat channel which can be secured with a password and accessibl
408 408
 </p>
409 409
 </div>
410 410
 </div>
411
-<div id="outline-container-org0422600" class="outline-2">
412
-<h2 id="org0422600">Jitsi Meet</h2>
413
-<div class="outline-text-2" id="text-org0422600">
411
+<div id="outline-container-org9f28087" class="outline-2">
412
+<h2 id="org9f28087">Jitsi Meet</h2>
413
+<div class="outline-text-2" id="text-org9f28087">
414 414
 <p>
415 415
 Experimental WebRTC video conferencing system, similar to Google Hangouts. This may not be fully functional, but is hoped to be in the near future.
416 416
 </p>
417 417
 </div>
418 418
 </div>
419 419
 
420
-<div id="outline-container-orgb944eab" class="outline-2">
421
-<h2 id="orgb944eab">Koel</h2>
422
-<div class="outline-text-2" id="text-orgb944eab">
420
+<div id="outline-container-orgbad5922" class="outline-2">
421
+<h2 id="orgbad5922">KanBoard</h2>
422
+<div class="outline-text-2" id="text-orgbad5922">
423
+<p>
424
+A simple kanban system for managing projects or TODO lists.
425
+</p>
426
+
427
+<p>
428
+<a href="./app_kanboard.html">How to use it</a>
429
+</p>
430
+</div>
431
+</div>
432
+<div id="outline-container-org6529912" class="outline-2">
433
+<h2 id="org6529912">Koel</h2>
434
+<div class="outline-text-2" id="text-org6529912">
423 435
 <p>
424 436
 Access your music collection from any internet connected device.
425 437
 </p>
@@ -429,9 +441,9 @@ Access your music collection from any internet connected device.
429 441
 </p>
430 442
 </div>
431 443
 </div>
432
-<div id="outline-container-orgbbbba81" class="outline-2">
433
-<h2 id="orgbbbba81">Lychee</h2>
434
-<div class="outline-text-2" id="text-orgbbbba81">
444
+<div id="outline-container-orgc0eae1a" class="outline-2">
445
+<h2 id="orgc0eae1a">Lychee</h2>
446
+<div class="outline-text-2" id="text-orgc0eae1a">
435 447
 <p>
436 448
 Make your photo albums available on the web.
437 449
 </p>
@@ -441,9 +453,9 @@ Make your photo albums available on the web.
441 453
 </p>
442 454
 </div>
443 455
 </div>
444
-<div id="outline-container-org6ff2173" class="outline-2">
445
-<h2 id="org6ff2173">Mailpile</h2>
446
-<div class="outline-text-2" id="text-org6ff2173">
456
+<div id="outline-container-orga4bfc9d" class="outline-2">
457
+<h2 id="orga4bfc9d">Mailpile</h2>
458
+<div class="outline-text-2" id="text-orga4bfc9d">
447 459
 <p>
448 460
 Modern email client which supports GPG encryption.
449 461
 </p>
@@ -453,9 +465,9 @@ Modern email client which supports GPG encryption.
453 465
 </p>
454 466
 </div>
455 467
 </div>
456
-<div id="outline-container-orgbed2d4b" class="outline-2">
457
-<h2 id="orgbed2d4b">Matrix</h2>
458
-<div class="outline-text-2" id="text-orgbed2d4b">
468
+<div id="outline-container-org672b48e" class="outline-2">
469
+<h2 id="org672b48e">Matrix</h2>
470
+<div class="outline-text-2" id="text-org672b48e">
459 471
 <p>
460 472
 Multi-user chat with some security and moderation controls.
461 473
 </p>
@@ -465,9 +477,9 @@ Multi-user chat with some security and moderation controls.
465 477
 </p>
466 478
 </div>
467 479
 </div>
468
-<div id="outline-container-org35530e4" class="outline-2">
469
-<h2 id="org35530e4">Mediagoblin</h2>
470
-<div class="outline-text-2" id="text-org35530e4">
480
+<div id="outline-container-orgce218ca" class="outline-2">
481
+<h2 id="orgce218ca">Mediagoblin</h2>
482
+<div class="outline-text-2" id="text-orgce218ca">
471 483
 <p>
472 484
 Publicly host video and audio files so that you don't need to use YouTube/Vimeo/etc.
473 485
 </p>
@@ -477,9 +489,9 @@ Publicly host video and audio files so that you don't need to use YouTube/Vimeo/
477 489
 </p>
478 490
 </div>
479 491
 </div>
480
-<div id="outline-container-org5500ed4" class="outline-2">
481
-<h2 id="org5500ed4">Mumble</h2>
482
-<div class="outline-text-2" id="text-org5500ed4">
492
+<div id="outline-container-orgb224245" class="outline-2">
493
+<h2 id="orgb224245">Mumble</h2>
494
+<div class="outline-text-2" id="text-orgb224245">
483 495
 <p>
484 496
 The popular VoIP and text chat system. Say goodbye to old-fashioned telephony conferences with silly dial codes. Also works well on mobile.
485 497
 </p>
@@ -489,9 +501,9 @@ The popular VoIP and text chat system. Say goodbye to old-fashioned telephony co
489 501
 </p>
490 502
 </div>
491 503
 </div>
492
-<div id="outline-container-orgc0f99a0" class="outline-2">
493
-<h2 id="orgc0f99a0">NextCloud</h2>
494
-<div class="outline-text-2" id="text-orgc0f99a0">
504
+<div id="outline-container-org2786fbb" class="outline-2">
505
+<h2 id="org2786fbb">NextCloud</h2>
506
+<div class="outline-text-2" id="text-org2786fbb">
495 507
 <p>
496 508
 Store files on your server and sync them with laptops or mobile devices. Includes many plugins including videoconferencing and collaborative document editing.
497 509
 </p>
@@ -501,9 +513,9 @@ Store files on your server and sync them with laptops or mobile devices. Include
501 513
 </p>
502 514
 </div>
503 515
 </div>
504
-<div id="outline-container-orga3e49f8" class="outline-2">
505
-<h2 id="orga3e49f8">PI-Hole</h2>
506
-<div class="outline-text-2" id="text-orga3e49f8">
516
+<div id="outline-container-orgaad15be" class="outline-2">
517
+<h2 id="orgaad15be">PI-Hole</h2>
518
+<div class="outline-text-2" id="text-orgaad15be">
507 519
 <p>
508 520
 The black hole for web adverts. Block adverts at the domain name level within your local network. It can significantly reduce bandwidth, speed up page load times and protect your systems from being tracked by spyware.
509 521
 </p>
@@ -513,9 +525,9 @@ The black hole for web adverts. Block adverts at the domain name level within yo
513 525
 </p>
514 526
 </div>
515 527
 </div>
516
-<div id="outline-container-org6d5133e" class="outline-2">
517
-<h2 id="org6d5133e">PostActiv</h2>
518
-<div class="outline-text-2" id="text-org6d5133e">
528
+<div id="outline-container-org0cb789f" class="outline-2">
529
+<h2 id="org0cb789f">PostActiv</h2>
530
+<div class="outline-text-2" id="text-org0cb789f">
519 531
 <p>
520 532
 An alternative federated social networking system compatible with GNU Social. It includes some optimisations and fixes currently not available within the main GNU Social project.
521 533
 </p>
@@ -525,9 +537,9 @@ An alternative federated social networking system compatible with GNU Social. It
525 537
 </p>
526 538
 </div>
527 539
 </div>
528
-<div id="outline-container-org82cb46a" class="outline-2">
529
-<h2 id="org82cb46a">Profanity</h2>
530
-<div class="outline-text-2" id="text-org82cb46a">
540
+<div id="outline-container-org6b2db26" class="outline-2">
541
+<h2 id="org6b2db26">Profanity</h2>
542
+<div class="outline-text-2" id="text-org6b2db26">
531 543
 <p>
532 544
 A shell based XMPP client which you can run on the Freedombone server via ssh.
533 545
 </p>
@@ -537,9 +549,9 @@ A shell based XMPP client which you can run on the Freedombone server via ssh.
537 549
 </p>
538 550
 </div>
539 551
 </div>
540
-<div id="outline-container-org0544cbf" class="outline-2">
541
-<h2 id="org0544cbf">Riot Web</h2>
542
-<div class="outline-text-2" id="text-org0544cbf">
552
+<div id="outline-container-org4dea572" class="outline-2">
553
+<h2 id="org4dea572">Riot Web</h2>
554
+<div class="outline-text-2" id="text-org4dea572">
543 555
 <p>
544 556
 A browser based user interface for the Matrix federated communications system, including WebRTC audio and video chat.
545 557
 </p>
@@ -549,9 +561,9 @@ A browser based user interface for the Matrix federated communications system, i
549 561
 </p>
550 562
 </div>
551 563
 </div>
552
-<div id="outline-container-orga52c58b" class="outline-2">
553
-<h2 id="orga52c58b">SearX</h2>
554
-<div class="outline-text-2" id="text-orga52c58b">
564
+<div id="outline-container-org7e88433" class="outline-2">
565
+<h2 id="org7e88433">SearX</h2>
566
+<div class="outline-text-2" id="text-org7e88433">
555 567
 <p>
556 568
 A metasearch engine for customised and private web searches.
557 569
 </p>
@@ -561,9 +573,9 @@ A metasearch engine for customised and private web searches.
561 573
 </p>
562 574
 </div>
563 575
 </div>
564
-<div id="outline-container-org8f2b9fe" class="outline-2">
565
-<h2 id="org8f2b9fe">tt-rss</h2>
566
-<div class="outline-text-2" id="text-org8f2b9fe">
576
+<div id="outline-container-orgcfc1af4" class="outline-2">
577
+<h2 id="orgcfc1af4">tt-rss</h2>
578
+<div class="outline-text-2" id="text-orgcfc1af4">
567 579
 <p>
568 580
 Private RSS reader. Pulls in RSS/Atom feeds via Tor and is only accessible via an onion address. Have "<i>the right to read</i>" without the Surveillance State knowing what you're reading. Also available with a user interface suitable for viewing on mobile devices via a browser such as OrFox.
569 581
 </p>
@@ -573,9 +585,9 @@ Private RSS reader. Pulls in RSS/Atom feeds via Tor and is only accessible via a
573 585
 </p>
574 586
 </div>
575 587
 </div>
576
-<div id="outline-container-org96317fb" class="outline-2">
577
-<h2 id="org96317fb">Syncthing</h2>
578
-<div class="outline-text-2" id="text-org96317fb">
588
+<div id="outline-container-org526d1e5" class="outline-2">
589
+<h2 id="org526d1e5">Syncthing</h2>
590
+<div class="outline-text-2" id="text-org526d1e5">
579 591
 <p>
580 592
 Possibly the best way to synchronise files across all of your devices. Once it has been set up it "just works" with no user intervention needed.
581 593
 </p>
@@ -585,9 +597,9 @@ Possibly the best way to synchronise files across all of your devices. Once it h
585 597
 </p>
586 598
 </div>
587 599
 </div>
588
-<div id="outline-container-org6118146" class="outline-2">
589
-<h2 id="org6118146">Tahoe-LAFS</h2>
590
-<div class="outline-text-2" id="text-org6118146">
600
+<div id="outline-container-org43bcb4f" class="outline-2">
601
+<h2 id="org43bcb4f">Tahoe-LAFS</h2>
602
+<div class="outline-text-2" id="text-org43bcb4f">
591 603
 <p>
592 604
 Robust and encrypted storage of files on one or more server.
593 605
 </p>
@@ -597,9 +609,9 @@ Robust and encrypted storage of files on one or more server.
597 609
 </p>
598 610
 </div>
599 611
 </div>
600
-<div id="outline-container-org7850375" class="outline-2">
601
-<h2 id="org7850375">Tox</h2>
602
-<div class="outline-text-2" id="text-org7850375">
612
+<div id="outline-container-org29d522e" class="outline-2">
613
+<h2 id="org29d522e">Tox</h2>
614
+<div class="outline-text-2" id="text-org29d522e">
603 615
 <p>
604 616
 Client and bootstrap node for the Tox chat/VoIP system.
605 617
 </p>
@@ -609,9 +621,9 @@ Client and bootstrap node for the Tox chat/VoIP system.
609 621
 </p>
610 622
 </div>
611 623
 </div>
612
-<div id="outline-container-org37c0a88" class="outline-2">
613
-<h2 id="org37c0a88">Turtl</h2>
614
-<div class="outline-text-2" id="text-org37c0a88">
624
+<div id="outline-container-org71eba9a" class="outline-2">
625
+<h2 id="org71eba9a">Turtl</h2>
626
+<div class="outline-text-2" id="text-org71eba9a">
615 627
 <p>
616 628
 A system for privately creating and sharing notes and images, similar to Evernote but without the spying.
617 629
 </p>
@@ -621,18 +633,18 @@ A system for privately creating and sharing notes and images, similar to Evernot
621 633
 </p>
622 634
 </div>
623 635
 </div>
624
-<div id="outline-container-org6042f9a" class="outline-2">
625
-<h2 id="org6042f9a">Vim</h2>
626
-<div class="outline-text-2" id="text-org6042f9a">
636
+<div id="outline-container-org95cabfd" class="outline-2">
637
+<h2 id="org95cabfd">Vim</h2>
638
+<div class="outline-text-2" id="text-org95cabfd">
627 639
 <p>
628 640
 If you use the Mutt client to read your email then this will set it up to use vim for composing new mail.
629 641
 </p>
630 642
 </div>
631 643
 </div>
632 644
 
633
-<div id="outline-container-org51cc377" class="outline-2">
634
-<h2 id="org51cc377">XMPP</h2>
635
-<div class="outline-text-2" id="text-org51cc377">
645
+<div id="outline-container-org07897b8" class="outline-2">
646
+<h2 id="org07897b8">XMPP</h2>
647
+<div class="outline-text-2" id="text-org07897b8">
636 648
 <p>
637 649
 Chat server which can be used together with client such as Gajim or Conversations to provide end-to-end content security and also onion routed metadata security. Includes advanced features such as <i>client state notification</i> to save battery power on your mobile devices, support for seamless roaming between networks and <i>message carbons</i> so that you can receive the same messages while being simultaneously logged in to your account on more than one device.
638 650
 </p>