435 Commits

Author SHA1 Message Date
f43ddd2a5a matterbridge - fix go download link creation 2022-05-10 22:55:27 +02:00
1914f83128 nextcloud - refactor variable names 2022-04-22 12:54:05 +02:00
8d1465ced9 sqn-completion - Suppress error for -pl (if seq has no profiles) 2022-04-22 12:53:41 +02:00
25962beb02 sequencer - don't create any config if only profiles should be listed 2022-04-21 23:22:21 +02:00
f20043fd61 gitea - don't create backup on GNU install call 2022-04-21 22:44:20 +02:00
63338eb466 grocy - add configuration with profile support 2022-04-21 22:43:18 +02:00
7a16eda8ad sqn-completion - also complete available profiles (-p) 2022-04-21 22:41:58 +02:00
1dfe86e69b sequencer - list profiles (-pl) with filter function 2022-04-21 22:40:59 +02:00
41c48407a8 WIP grocy - Installation, upgrad and backup 2022-04-20 23:14:54 +02:00
db8d906ece matterbridge - add option to choose CPU architecture 2022-04-13 16:46:47 +02:00
57ac4acf79 WIP matterbridge - steps to build matterbridge from source incl. installing go 2022-04-08 21:23:04 +02:00
b7e798eeca matterbridge - preparing step to build from source using go 2022-04-04 22:56:10 +02:00
a1e0217759 download.sh - Fix readar ExecStart in systemd service 2022-03-25 09:03:18 +01:00
cd19dfcc98 snmp.sh - adding pihole extend 2022-03-25 09:02:34 +01:00
471da5f2d4 git.sh - set git aliases 2022-03-25 07:45:04 +01:00
5b6fa2b59d sqn-completion - remove obsolete commented line 2022-03-16 01:09:35 +01:00
d57d7b2c0b shellchecked 2022-03-16 01:06:35 +01:00
739a4b1e7c sqn-completion supports seqs with spaces in their names
sqn-completion now shellcheck compliant and correctly indented
2022-03-16 01:05:29 +01:00
48b5965969 sequencer - simplified sqn-completion naming 2022-03-15 09:44:53 +01:00
9c8e0ab741 raspberry - add first setup notes 2022-03-14 21:46:34 +01:00
15f537c90d matrix-commander - run always as current user 2022-03-14 21:44:55 +01:00
992868b14d sequencer - correct indentation using .editorconfig 2022-03-14 21:31:53 +01:00
71612aef94 Add .editorconfig and correct indentation for many seqs 2022-03-14 21:27:29 +01:00
bb8b54597a vim - step to install plugin editorconfig and new version of indent script 2022-03-14 20:50:16 +01:00
fb67ff42f4 sequencer - add subdir to fallback path
Fix standard sourcing
2022-03-13 13:25:37 +01:00
7b33585405 matrix-commander - run as current user 2022-03-13 10:48:03 +01:00
729f4923f9 installCompletion - Fix bashrc filename 2022-03-13 08:02:20 +01:00
eed4089f9e Fix normal install without arguments (test BASH_SOURCE[0] 2022-03-13 07:28:44 +01:00
cf52eb3187 Fix normal install without arguments 2022-03-13 07:07:26 +01:00
44b5482772 sequencer - new options -- (end options) ++ (quick start step 1)
Update template
2022-03-12 15:47:51 +01:00
11198a3b46 matrix-commander - Rearange steps call matrix-commander as first 2022-03-12 15:11:01 +01:00
0911473db6 Fix typo 2022-03-10 13:56:16 +01:00
86509453cc matrix-commander - additional step for first run and sending a message
More notes about verifiying matrix-commander in element
2022-03-10 13:46:01 +01:00
efac859fac fhem.sh - add step to download latest speedtest python script 2022-03-09 22:20:00 +01:00
57a986fe40 matrix.sh - adapt room delete to new ROOM API version 2022-03-09 22:18:08 +01:00
91327a2973 sequencer - make use of test -n and for finish message 2022-03-09 12:05:05 +01:00
8cf808d70b matrix-commander - Finalized for manual installation 2022-03-09 12:01:31 +01:00
3fc647aef8 kodi - fix typo for daemon-reload 2022-03-09 11:42:00 +01:00
1d6b4c3b53 matrix-commander - First draft for installation 2022-03-08 17:35:08 +01:00
c4c6007b00 Tread symbolic link target as file for user seqs collection directory 2022-03-07 00:33:33 +01:00
b894a756ea Support installation to different directoy
Introduce configuration file to set a custom seqs collection
2022-03-07 00:15:27 +01:00
56765a0884 Mayan-EDMS - New dependencies for version 4.2 2022-02-27 12:20:22 +01:00
9e81cd32fe Improve output 2022-02-27 11:32:55 +01:00
3f93e6a846 Sequencer - sourcing config independent from dry run again 2022-02-26 23:05:29 +01:00
ebcdbb88bd calibre-web - new seq for installation from pip and basic setup 2022-02-26 23:03:29 +01:00
141b16e804 Sequencer - Allow further arguments and steps with '-c' 2022-02-23 12:44:54 +01:00
7c89c99a61 Sequencer - determine system text editor and ask before seq configuration creation 2022-02-23 11:27:47 +01:00
cddfeb43dd Sequencer - Refresh step info output for help and execution context 2022-02-20 21:57:39 +01:00
bc706fb121 mysql - adding sanity check for backup target 2022-02-17 08:42:50 +01:00
cec9739372 Unbound - fixing extend line and adding notes step 2022-02-17 08:41:40 +01:00
4c032e6b5e Friendica root sanity check and small info enhancement 2022-02-17 08:40:10 +01:00
78189e43e7 New seq to setup vim according to sequencer git wiki 2022-02-16 15:47:14 +01:00
487c812364 WIP: beginning of new seq to install matrix-dimenstion 2022-02-16 15:46:38 +01:00
4dfc6cdce9 Small improvemnt for addConfig() if target does not exist for dry run 2022-02-16 15:18:18 +01:00
1c99aee146 Small fixes 2022-02-15 14:44:35 +01:00
653d233586 Enhanced output with new features of sequencer 2022-02-15 14:01:52 +01:00
dcdb6b45a3 Enhanced exep() incl api help
New helper function escpath() incl api help
2022-02-15 14:00:38 +01:00
1a44ab50f1 Adding steps for install/upgrade readarr 2022-02-15 10:20:24 +01:00
fdfcba54ee Secret can be set from config and internal data is made available 2022-02-11 10:31:58 +01:00
637c248b40 Fix case order for outColor() 2022-02-11 10:20:16 +01:00
15ced9d2dc Fix color none not working for outColor() 2022-02-10 11:41:33 +01:00
9a20a2d374 Gitea - Now configurable with default pathes in one place for better backup/migration 2022-02-09 16:01:42 +01:00
58a8ec6eae Ability to show sqn_ alias in sequencer help
outColor accepts a custom color number (0-255)
2022-02-09 15:44:22 +01:00
a9491aa84a Better configuration creation for php 2022-02-08 12:06:00 +01:00
d2fd71d5c9 Suppress output when used with -qq 2022-02-07 23:55:46 +01:00
dfa5804316 Support to download OS 64 bit version 2022-02-06 15:04:40 +01:00
839d42c39b Multiple enhancements about database creation
New steps to revoke and show privileges
2022-01-27 10:17:52 +01:00
b34447ad9a Fix help output 2022-01-25 14:44:05 +01:00
6dd40bc6c2 Improve help output with latest changes from sequencer 2022-01-23 23:06:46 +01:00
e641373a57 New steps to disable various hardware elements
Improved help output
2022-01-23 22:42:03 +01:00
38d635446e Improved separation of step cluster for the help output 2022-01-23 22:38:57 +01:00
b6e4359965 Cosmetic changes 2022-01-22 00:27:43 +01:00
b1acff2d70 New step to remove generated previews from NC data directory 2022-01-22 00:18:34 +01:00
9507922968 Use realpath for buTarget directory 2022-01-22 00:05:29 +01:00
feed3076ba Make use of new way to display step arguments (echoinfoArgs) 2022-01-16 23:40:59 +01:00
1edef40342 Add possibility to -h to display info only for one specified step
New way to display step arguments by moving the cursor around with escape sequences
2022-01-16 23:37:50 +01:00
f30f2ea205 New step with setup notes 2022-01-11 21:49:59 +01:00
be54b5cfba Additional commands needed for oauth client compatibility 2022-01-11 21:43:09 +01:00
c296c07373 Update step configuration handling
Reverse logic for supervisor configuration update
2022-01-11 21:42:26 +01:00
06f960d96d Update step configuration handling 2022-01-11 20:37:24 +00:00
51a3a8b593 Step to reset and rescan the autioplayer library in the background 2021-12-31 17:42:49 +01:00
f0e9bbe4e0 On upgrade, tansfer also a custom landing page 2021-12-31 17:41:48 +01:00
1f946cd9a2 New seq with basic functionality to install OliveTin from github 2021-12-31 11:27:57 +01:00
80e2fadf12 Detect current version as upgrade information
Add step for troubleshooting notes
2021-12-31 07:13:06 +01:00
e346a378c4 New steps to install/upgrade prowlarr
Started work on step to upgrade bazarr
2021-12-07 20:15:29 +01:00
e686dbaf9d More transmission monitoring steps 2021-12-07 20:11:53 +01:00
c861bb3a13 Matrix: Add python dep. for URL preview during installation 2021-10-04 11:55:50 +02:00
9525aed587 Sequence with basic database handling for freeradius 2021-09-14 12:00:06 +02:00
f1385197d8 New option to execute all steps regardless of continuity 2021-04-21 23:00:36 +02:00
2ddfefa646 Introduce configuration file 2021-04-21 22:57:58 +02:00
867071eca0 Add prefix to bash completion install function 2021-04-19 22:37:20 +02:00
5db0165c49 Using variable for all install targets 2021-04-19 22:35:58 +02:00
4f2d80bbc9 New steps to install bazarr 2021-04-19 22:21:31 +02:00
b7f41c4ec7 Add option to not remount target on backup 2021-04-19 22:01:50 +02:00
d6b11898a2 Update for debian dependencies 2021-04-19 21:57:06 +02:00
70b4056a7f Step for adding ufw rules 2021-04-19 21:46:15 +02:00
37069952d4 Provide bash-completion an aliases for availale sequences including installation script 2021-04-15 14:54:29 +02:00
2872901924 Add step to reset kodi music library (deleting database files) 2021-04-13 10:14:05 +02:00
b2a851c4af Refactor simple internal variables so that overrides from sequences get more unlicely 2021-04-13 10:09:37 +02:00
b8586cfc7c Add steps for dhcp and unbound extends 2021-04-08 16:17:22 +02:00
c1eb864fb9 Output more information for step status 2021-04-08 15:20:20 +02:00
64abe2f28f Verifies profile support before executing profile options
New option to list available profiles
2021-04-08 15:19:43 +02:00
d3b3a8d60b Download to tmp first in case of errors
database creation from external script
2021-04-08 09:07:58 +02:00
75663b3108 Fix -c starting step 1 with -qq if no configuration is available 2021-04-07 10:02:19 +02:00
2b7bd987cb Bump mayan version to 3.5.7 2021-04-07 10:00:40 +02:00
6f0227a6ee Enhanced public ip detection
First try with upnpc to acquire ip via router, then fallback to extrenal dns query
2021-04-01 14:12:59 +02:00
d2bf4d8677 New function to exit sequence if another instance of it still runs 2021-04-01 14:05:02 +02:00
84051c6b2a Update to support also debian as target system 2021-03-31 16:23:38 +02:00
14668700a7 Step to add ufw rules 2021-03-31 16:22:45 +02:00
90bff659de Use systemctl for all operations 2021-03-31 16:22:18 +02:00
a466615d3a Adding steps for installing lidarr 2021-03-31 16:20:40 +02:00
9da7a80846 Add setup notes 2021-03-31 16:19:57 +02:00
dfae33ff23 Enhanced step for cifs
Reduced basic secure VPN setup
2021-03-29 00:09:16 +02:00
bb19a0f8ad New steps for install, ufw rules and configuration notes 2021-03-28 23:44:15 +02:00
b46c4b6302 Add steps to install danted proxy and disable apt daily activity
Various other enhancements
2021-03-28 23:43:02 +02:00
04abf6c6b7 New step to install cifs requirements incl. notes
Add note on how to disable ipv6
2021-03-28 23:41:35 +02:00
c75ec7ddeb Check and install rsync if missing 2021-03-28 23:39:46 +02:00
52d03c3730 Add step for ufw rules to access rpc port 2021-03-28 23:39:17 +02:00
741d0c74c9 New sequence for installing openvpn with setup of custom scripts 2021-03-27 05:35:11 +00:00
260daa009c Output error if step_config fails
Small enhancement of the template
2021-03-27 05:33:38 +00:00
86cee821ba Extended log option for updateip 2021-03-26 22:42:27 +01:00
881d8bbe3f Extending notes how to reset root password 2021-03-24 14:57:29 +01:00
65f8ab8dc8 Small template adjustement
New variable SCRIPT_FILE holding script file name
2021-03-24 14:46:53 +01:00
e4a88178ae Sequence to install coturn and step for updating public ip
TODO configuration notes
2021-03-24 14:45:09 +01:00
b4e297f7ab Sequence for an advanced downloader setup 2021-03-21 17:28:32 +01:00
f6ccc54556 Sequence to install couchpotato 2021-03-21 17:27:52 +01:00
669247836a Add basic secure VPN setup and cifs mounts 2021-03-21 17:27:23 +01:00
bb7d187d64 Small template extension for APT option -y 2021-03-21 17:22:57 +01:00
b88a69e68b Add step to restrict client access 2021-03-20 21:53:12 +01:00
936e58c72b WIP new sequence for transmission daemon 2021-03-19 01:45:03 +01:00
7face5cd4a step_config must return 0 on success 2021-03-19 01:44:22 +01:00
8e63bbe7df Sequencer new option to open sequence config file when initialised using initSeqConfig
Sequences with exit in step_config, changed to return to support opening config file on first run
2021-03-19 01:32:59 +01:00
ab1f9f761e New sequence for aria2 2021-03-18 00:43:09 +01:00
07828f0d6f Bump mayan version to 3.5.5 2021-03-13 22:03:23 +01:00
c18be0b7ad Minor improvements 2021-03-13 22:03:01 +01:00
c5c4623514 New sequence to install redis including basic installation notes 2021-03-13 20:43:35 +01:00
1ab8ec6296 Setup official nginx repository
Installation notes
2021-03-13 20:43:09 +01:00
98d8de1eee Fix variable declaration 2021-03-12 17:17:03 +01:00
cd4313cbf1 Adding notes for boot from HD 2021-03-05 22:32:17 +00:00
52be30dc15 Step to change hostname 2021-03-05 21:10:51 +00:00
7d8c3c794f Steps for essential deps and setup locales 2021-03-05 16:31:31 +00:00
9839cf066a Sequence to setup and install a debian image for a raspberry pi 3b+ or 4 2021-03-05 12:19:21 +01:00
f3535f6b2c Steps to send kodi logs to syslog using a systemd service 2021-03-02 00:11:08 +01:00
262b75fd8b New step to send kodi log to syslog 2021-02-26 22:05:04 +01:00
12a2d52b05 New step to install nagios plugin (services)
Colored output for text only steps
2021-02-19 14:48:05 +01:00
3001515720 New step how to activate syslog server (receiver) 2021-02-19 14:47:12 +01:00
cccbc75c6d New step for distribution detection
Adapt echo to echoseq
2021-02-19 14:46:06 +01:00
2295381a66 Step renamed to listuser
Added charset utf8
2021-02-19 14:45:00 +01:00
41fd3d3861 Adding colored output support (outColor)
Extended seq template
2021-02-19 14:43:41 +01:00
1a3fb55fbd Creating backup target directories 2021-02-18 22:02:52 +01:00
9f9f684dd5 Adaptions after frist install test 2021-02-18 21:42:26 +01:00
5539c6b78e Provide possibility to enter Access Token on demand 2021-02-17 10:19:40 +01:00
505065bb3e Improve createdb step to take various arguments making createdb_utf8mb4 obsolete 2021-02-16 22:59:23 +01:00
aaf14ba332 Adapt installation process to latest version
WIP steps for complete backup (montly|daily)
2021-02-16 22:58:17 +01:00
660498ffea Added configuration 2021-02-14 21:50:23 +01:00
f104950cbd Prepare backup steps 2021-02-14 18:24:01 +01:00
a485904c88 Already installed message to stdout not stderr 2021-02-14 18:22:38 +01:00
a4e453ee22 Add syslog logging option for sequence ebackup 2021-02-04 17:56:12 +01:00
213180013a New step verify (against profile settings only for now)
Enhanced step restore with more options
2021-02-03 23:53:46 +01:00
6dd7c0d00c fix typo 2021-02-02 22:57:28 +01:00
88af37f925 New sequence for encrypted backups supporting profiles using duplicity 2021-02-02 22:56:14 +01:00
548c0bfc1c Added step for notes 2021-02-02 22:52:50 +01:00
e2c095eb7d New seq for encrypted profile based backup management using duplicity 2021-02-01 22:26:40 +01:00
ad18a2b8d5 Fix always setting SEQ_CONFIG_HOME 2021-02-01 22:24:49 +01:00
e0daa360e9 New global variable SEQUENCER_ARGS containing sequencer options to pass down to other seqs eventually 2021-02-01 22:22:15 +01:00
3c132ed4e2 Adding variables CONTEXT_HELP and SEQ_PROFILE_NAME to the API documentation 2021-01-31 22:18:57 +01:00
33775ffb1d Refactored template creation
Fix obsolete escapes in sequencer help output
2021-01-31 19:48:56 +01:00
4c7eae13c4 New function "configuration profiles" for sequencer (initSeqConfig)
Changed usage definition to "cat" instead of echo
2021-01-31 17:33:03 +01:00
370a042c8b Major: Doesn't stop with option -q(q) if now step is given.
Major: Seqs config files are created with permissions 600

Minor: Further reduction of messages when using -qq
2021-01-31 11:20:18 +01:00
38c24693c9 Fix typo needed for Ip4 only mode 2021-01-30 21:02:12 +01:00
b50b74235c Adding sender dependet relay configuration step
Enhanced testmail step
2021-01-28 15:52:16 +01:00
b5e5bcba66 Seq to upgrade an existing torrentwatch installation
Installation is WIP
2021-01-27 21:43:02 +01:00
b29a5c3c2b Content filter only needed for incoming mail 2021-01-20 16:11:03 +01:00
784be2b850 Add notes to clean outgoing header 2021-01-20 16:07:36 +01:00
d52fb92920 Clustering continous step numbers for better readability 2021-01-20 13:29:57 +01:00
1f528e2c34 Adding alias for listing spam and ham count 2021-01-20 13:27:55 +01:00
0534fd052a Fix postfix steps (missing extend for postfixdetailed, missing dependencies for postfix-queues) 2021-01-20 13:27:02 +01:00
a1cc1c7f2d Adding notes how to configure spell checking 2021-01-20 13:25:04 +01:00
d4cdff72c4 Fix missing " as string termination
Remove code to cluster steps as this is done by sequencer.sh with version 11.0.4
2021-01-20 13:24:12 +01:00
a1c76d1f7a Copy also custom background images to new version 2021-01-19 16:38:42 +01:00
22e10edbad New steps for fail2ban and postfix (postfix-queue postfixdetailed) 2021-01-17 22:44:45 +01:00
6c2dc20d1b New seqs for spamassassin and postgrey 2021-01-17 13:47:08 +01:00
9020e87561 Adding comments to added rules 2021-01-17 13:45:59 +01:00
9013f9224c Notes update (Auto-subsribe mailbox folder; Execution of external programs) 2021-01-17 13:45:09 +01:00
e7b524ef2c Creating also log directory 2021-01-14 23:27:59 +01:00
f874b7f03a Adding postmaster address to lmtp configuration 2021-01-14 21:48:35 +01:00
fcde8b8eba Adding steps for installation including php dependencies 2021-01-14 21:48:06 +01:00
be84057358 Use systemd timer for fetchmail plugin 2021-01-14 21:17:35 +01:00
c690c173eb Sequence to install and do a basic setup for the firewall ufw 2021-01-14 21:14:58 +01:00
9c9af7f7f4 Adding sequence for fail2ban finally and updating supporting files 2021-01-14 21:13:38 +01:00
688d1c871b Inital commit for mailserver related seqs 2021-01-12 22:32:09 +01:00
9f262616fb Fix failing step name resolution on singe step execution (-s) 2021-01-12 22:30:51 +01:00
6122b9d7ce Adapt upgrade step to addon archive content structure
(see https://fd.winklerfamilie.eu/display/f3ad7b1c-175f-f431-45dd-84c383787445)
2021-01-08 13:35:46 +01:00
4d925dbc4a Step sendkey: add ssh option to force Ipv4 2021-01-03 01:42:39 +01:00
066dcfcdcd New step to document steps to migrate synapse to another server
Fix raspi dep. typo
2020-12-27 23:12:33 +01:00
afec7878a3 Split step for install and default configuration 2020-12-27 19:14:27 +01:00
ca169beec6 Added to API documentation 2020-12-27 00:02:33 +01:00
fce45e26f5 New step to debloat postgres database 2020-12-27 00:01:42 +01:00
0bddd5f1ce Add steps to delete room and "purge" rooms with no local users 2020-12-26 18:20:30 +01:00
ae83eedec4 Make helper variables local to prefent side effects 2020-12-26 18:09:51 +01:00
232b05aa95 More calls to admin API which need access token (list user, list rooms, list room members) 2020-12-26 00:35:08 +01:00
805d543d3f Adding Raspberry Pi OS specific dependencies discovered during first installation attempt 2020-12-25 01:48:05 +01:00
aa8847af02 Fix typo 2020-12-25 01:36:35 +01:00
b33db9d357 Deleted unused variable 2020-12-25 01:35:57 +01:00
4b4dce7f66 New seq to install and upgrade matterbridge from github on raspberrypi os 2020-12-25 01:33:20 +01:00
7e49facd4d Register new users always on localhost (needs binding to localhost as well) 2020-12-25 01:32:26 +01:00
8d96d7e38a WIP; SD card can be fully prepared on any linux PC (cmdline.txt change, resize second partition) 2020-12-23 23:39:51 +01:00
0a92b49cc7 Fix continous execution ignoring return values and thous jumping number boundaries 2020-12-23 23:37:33 +01:00
09300234fc Added step to downgrade xmpp dependencies to avoid "callbackIQ crash" 2020-12-21 12:24:47 +01:00
0fe7eac8f3 Fix git config command help output after installation 2020-12-19 11:07:34 +01:00
30aef29aab Github download file name change fixed 2020-12-10 10:55:02 +01:00
3d85c1353d Remove temp backup in /var/www to provide better unattended backup 2020-11-24 11:27:34 +01:00
b4990b3668 Add step to exe fhem command from command line 2020-10-23 22:09:12 +02:00
ec93e655f3 Step to reset a users password 2020-10-13 23:54:59 +02:00
a8838fa5da Update info output 2020-10-12 22:16:43 +02:00
11f001ede0 Adding step to list databases 2020-10-12 22:13:31 +02:00
f5d672f609 Update fhem version and add known serial adapter to udev rules 2020-10-01 14:08:06 +02:00
d714c6b7f9 New step "updatecheck" to check if a new version is available 2020-09-30 21:48:19 +02:00
5aba72ee49 Sequencer returns returnvalue of last executed step 2020-09-30 21:46:50 +02:00
84a798dea5 Add step to remove a registered user 2020-09-30 12:32:39 +02:00
b163e53b37 Seq to upgrade and backup an existing element-web installation 2020-09-30 12:29:06 +02:00
1ff20e3918 Seq for installing and upgrading motioneye 2020-09-21 22:05:49 +02:00
44eb276b1c Update download URLs and renamed moved backup folder to include date and time 2020-09-21 14:23:25 +02:00
7a83a5f8a1 Fix VCHI initialization failed message for snmp raspberry extend 2020-09-16 09:39:46 +02:00
f1ef00d34f Use su to call psql 2020-09-15 14:57:32 +02:00
424fde64f8 Fix invalid function definition 2020-09-15 14:54:08 +02:00
c5c4c3a962 First version for postgresql dedicated seq 2020-09-10 16:48:24 +02:00
f28e4523a4 Adding configuration abilities to matrix.sh 2020-09-07 15:53:45 +00:00
f58900be1f Addings seqs for upgrade, version and restart 2020-09-06 23:25:59 +00:00
fd6628196d Updates after first successful installation 2020-09-06 22:27:18 +00:00
2cd478aae3 Simple installation script 2020-09-05 14:34:15 +00:00
c0cfddb54a First untested seq for matrix server synapse 2020-09-05 00:16:58 +02:00
66bc680a16 Div. improvements e.g. PartUUID detection changed, SD card detection changed
Comments for step 4 boot from HD extended
2020-08-29 23:36:11 +02:00
74ec53ae18 Step to restart network card eth0 without reboot 2020-08-20 22:40:00 +02:00
c984905550 Add additional checks for correct mounting and tagert being writeable 2020-08-13 16:58:22 +02:00
3dd31c51ea Adding step to repair horizon GUI 2020-07-22 22:57:23 +02:00
fe1318a7b2 Bump mayan version to 3.4.11 2020-07-19 21:28:37 +02:00
adc3deba18 Reflect changes in post upgrade procedure 2020-07-19 21:28:17 +02:00
e0ba86d48f New seq to upgrade an existing friendica installation 2020-07-13 16:58:21 +02:00
edeb3553a0 Adding definition to prefend friendica warning 2020-07-13 16:53:26 +02:00
f3b774839c Wireguard installation and basics for client usage on raspbians 2020-06-25 00:27:37 +02:00
e348d0ffb7 Fix configuration template name 2020-06-04 15:28:13 +02:00
a7a632523d Using sequencer configuration handling and making it more foolproof 2020-06-04 15:20:37 +02:00
7a61dcd718 Refining initSeqConfig function
Option to choose if empty config should be created (Is not by default)
2020-06-04 15:19:17 +02:00
4c50812346 Version can be supplied manually as parameter (if latest doesn't match)
Separated postupgrade step
2020-06-03 16:46:47 +02:00
d0cdd8d271 Bump version to 3.4.9
Adding option to not update supervisor configuration
2020-05-26 17:26:37 +02:00
74b9ce31d2 Default remote rsyslog connection to tcp 2020-04-30 22:23:48 +02:00
59cc2c7b70 Show password during entry 2020-04-30 22:22:42 +02:00
ab6283de9b Adding SSL configuration using values from the config file
Other smaller improvements
2020-04-29 23:08:18 +02:00
027737103a WIP Adding installation steps, and most of the managment functions
TODO SSL configuration
2020-04-23 22:30:20 +00:00
d708ba8ab3 WIP working group managemnt using echo to pipe LDIF directly to ldap commands 2020-04-22 21:09:40 +00:00
cd0e5b39a2 Fix moving default nginx configuration 2020-04-19 11:57:42 +02:00
ffb04bdcb4 Fix restart command 2020-04-19 02:26:29 +02:00
4b4b0531c7 Fix docker dns modification
Enhance step purge
2020-04-17 18:58:17 +00:00
7abb25ea05 Not starting pyload after upgrade 2020-04-17 18:15:07 +02:00
8371eefa97 Bump php version to 7.3 2020-04-16 21:08:02 +00:00
ff1a4eeb8f Install curl as dependency before setting up repository 2020-04-16 21:07:05 +00:00
4bfeda23da Adding step infos 2020-04-16 17:38:35 +02:00
6099b25517 New step to setup official repository for the latest version 2020-04-16 17:17:38 +02:00
c4a796851d Adding post installation tasks as information until they will be implemented automatically 2020-04-16 14:25:09 +02:00
b6e3b0d07a Bump mayan version to 3.4.5
Redis password needs to be manually adjusted in /etc/supervisor/conf.d/mayan.conf after the upgrade
2020-04-14 16:01:36 +02:00
3c66148f28 Initial WIP 2020-04-13 13:34:40 +02:00
a3d34cdc23 More user info when disabling LED 2020-04-11 20:14:05 +02:00
39e2597ba9 Update sequence for mayan EDMS versions >= 3.4
Bump mayan version to 3.4.4
2020-04-11 19:04:14 +02:00
61284cf46f Bump mayan version to 3.3.15 2020-03-13 18:25:55 +01:00
e28f71d320 Fix typo in command parameter 2020-03-13 17:46:01 +01:00
b735606657 Upgrade nextcloud steps added to sequence 2020-03-13 17:43:38 +01:00
5f26548299 Clarified user output about sourcing config files
Small fix for seq template
2020-03-13 17:43:24 +01:00
3d04a5ecc3 New sequence to backup and update a roundcube installation 2020-02-21 11:38:56 +01:00
ab91cc1ab9 Added ability to create a database dump at given position 2020-02-21 11:37:47 +01:00
f3cd19e22e Fix false logic for config detection in template 2020-02-20 10:56:29 +01:00
85c26b580b Bump mayan version to 3.3.13 2020-02-17 10:17:05 +01:00
5adba4e61c Work on help output 2020-02-17 09:57:25 +01:00
a4c51b5ee3 Reduce rngd messages with more general regex 2020-02-15 17:41:54 +01:00
8e3b0355ff Repeat password entry and add option to stop after authentication entry creation
todo: fix loose dependency to php which leads to error on every run
2020-02-14 22:03:41 +01:00
809d40e8a2 Rewrite add user to reflect changes in adduser syntax 2020-02-14 22:01:29 +01:00
317b2088f0 Add step to upgrade to latest version
Raised dependency to sequencer 10
2020-02-11 11:36:21 +01:00
Martin Winkler
f83383cd51 WIP continue 2020-02-10 23:03:25 +01:00
e65b619ca7 Bump mayan version to 3.3.12
Pass all arguments to management script
2020-02-10 15:46:32 +01:00
0f037ec8a1 Add step to setup scheduler; starting from 10.8
Rebuild view cache post upgrade
2020-02-10 15:45:24 +01:00
94f47d1cc8 Changed sendlist keyword u (update) to c (command) for clarification
Starting output for sendkey improved
2020-01-29 13:08:05 +01:00
916e7d55d2 Bump mayan version to 3.3.9 2020-01-24 23:20:24 +01:00
259338ca83 Fix pull target of upgrade to be variable
Restart pixelfed service as part of post update procedure
2020-01-24 23:20:00 +01:00
cc9fd79693 Don't ask for template creation if sequencer.sh was called directly with -h 2020-01-24 19:45:11 +01:00
a26a0db9ca Ability to add a new database with privileges for an existing user 2020-01-24 19:26:37 +01:00
e1bada678b Get latest Veresion of gitea from github
fix #4
2020-01-18 23:26:12 +01:00
0cded7c888 Advanced help output showing actual paths before step start 2020-01-13 18:12:02 +01:00
60f6d04c3b Fix missing error message for invalid step doing a selection of steps 2020-01-13 17:38:31 +01:00
a657473871 Fix running step_config if first step is invalid
sequencer.sh now returns with last result
2020-01-13 17:18:11 +01:00
31b85395d6 New budir option to take backup target from config
Rsync doesn't cross filesystem boundaries any more

Important partitions need to be backup separately using "budir"
2020-01-13 16:42:29 +01:00
84855cded6 Cosmetic improvement to remove double slash in verbose output when backing up root 2020-01-13 15:44:55 +01:00
7826addc26 Fix exclude rule for backup folder and backup logs
Before every file in the tree containing backup was excluded
2020-01-13 15:44:05 +01:00
29ede5409b Provide basic installation instructions 2020-01-13 14:12:30 +01:00
0ec36247f7 Use available configuration file if exists in the same directory as the template 2020-01-13 14:12:04 +01:00
e883306fc9 Making use of new api function to manage configuration in user home 2020-01-13 11:49:37 +01:00
4b4df3132a New api function to manage seq configurations (create/use)
Seq template is generated by sequencer.sh; deleting static template
2020-01-13 11:48:15 +01:00
2e6984aac8 New option -qq to suppress regular output
Usefull when step are called from another seq
2020-01-05 15:04:20 +01:00
8d303bbcbc Outsourced mysql related steps to own seq 2020-01-05 15:02:53 +01:00
da30fc84b8 Use seq mysql.sh to output available mysql databases 2020-01-05 14:46:44 +01:00
0cb059a58f New seq for installing fhem (on buster)
Detect OS distribution for special xmpp support
2020-01-04 12:43:07 +01:00
d2691d4d93 New seq for nextcloud related tasks
New step: Delete IP from bruteforce table
2020-01-04 01:31:09 +01:00
99375dd4f3 New step to upgrade only office installation 2020-01-01 23:29:18 +01:00
2688d60f6d Small documentation update 2020-01-01 23:28:20 +01:00
bff087d731 Bump mayan version to 3.3.7 2020-01-01 23:27:49 +01:00
dab84f4d67 New sequence to provide various backup options
Rsync included
2019-12-31 00:16:12 +01:00
ac011b6564 Comment cleanup and sequencer path fix 2019-12-31 00:15:04 +01:00
d369913e9f step() function did not provide argument pass-through 2019-12-31 00:13:54 +01:00
02cccb71bd WIP boot from HD 2019-12-28 14:57:55 +01:00
ef8af4b5b5 Fix escaping backslash 2019-12-27 16:25:34 +01:00
404646e6a2 Fix certificate location 2019-12-27 16:24:53 +01:00
b5447f6f06 WIP simplification of read sd/hd functions 2019-12-25 18:57:00 +01:00
49749cdeeb Adding alias for turning off LED 2019-12-24 15:34:17 +01:00
0575aad054 WIP on preparing SD card
New step to turn off power LED
2019-12-24 15:32:10 +01:00
742fc70798 WIP new steps to download raspbian lite image and write to SD card 2019-12-23 23:14:13 +01:00
ef572f9d7e Bump sequencer revision to 9
New API function echoinfo

New option -s to execute only one step

Step argruments are also passed to step info function
2019-12-23 23:13:11 +01:00
f90e95461e New seq for basic raspberry pi setup
WIP
2019-12-23 06:29:17 +01:00
ebe2bee4fd Bump mayan version to 3.3.6 2019-12-19 23:27:51 +01:00
be420094b5 Fix: escaping start of line character 2019-12-19 23:27:29 +01:00
d5274f159e Adding steps to reduce RNGD syslog entries (starting with Raspian buser 2019-12-16 13:39:54 +01:00
4dd128d00f Absolute path for sequencer.sh needed for automatic execution via cron 2019-12-16 13:28:39 +01:00
53d51f8cee Added steps to configure nginx status
Todo: enhancement for automatic nginx configuration
2019-12-14 21:10:47 +01:00
c01371a21c Added steps to configure php-fpm status
Todo: enhancement for automatic nginx configuration
2019-12-14 15:10:25 +01:00
c88ae510ab Bump mayan-edms version to 3.3.5
Make use of latest sequencer features
2019-12-14 00:37:35 +01:00
23924645cb fix sequencer.sh include 2019-12-14 00:07:55 +01:00
bc5d30f400 New sequence certbot for install and update of certificates 2019-12-13 23:48:06 +01:00
91f9f8a8da endCheckEmpty uses full DESCRIPTION as error message, if available 2019-12-13 23:47:02 +01:00
2041621d2b Using new sequencer.sh features
No functional change
2019-12-13 23:19:23 +01:00
0cf41c708d Added basics sequence as collection simple setup tasks
Starting with ssmtp
2019-12-13 12:20:31 +01:00
d182f5e0c6 Small output update 2019-12-13 12:18:51 +01:00
358cff38b1 New sequence to manage rsyslog config
Only client configuration for now
2019-12-12 23:51:26 +01:00
9a303b634f Extended addConf with file support for SOURCE 2019-12-12 23:49:16 +01:00
790ba88d7d Preparation for fail2ban script 2019-12-12 20:58:06 +01:00
6cfcee6d20 Bump Sequencer required version to 8 2019-12-12 11:01:54 +01:00
d1df177afb Onlyoffice port default to 80 2019-12-12 11:00:41 +01:00
e761cbacdf Make user configuration for onlyoffice sequence 2019-12-12 10:59:24 +01:00
7e3fb265c4 Ignoring local .cfg files (step user configuration) 2019-12-12 10:58:37 +01:00
d6aba7d06f Bump sequencer.sh version to 8.0.0
Support for function step_config which is called once before any step

Output alias on stopping at a step if available
2019-12-12 10:57:28 +01:00
8d8779a58a Add support to start onlyoffice docker container with JWT_SECRET
Docker prune added as step
2019-12-11 23:43:12 +01:00
68a16b2fdd Fix: step arguments not passed on correctly if strings with spaces were involved 2019-12-11 23:16:35 +01:00
1ceefcfe95 New seq onlyoffice which installs latest docker and latest onlyoffice image
todo: upgrade steps
2019-12-11 13:41:04 +01:00
100f0f9db9 Update with new sequencer features 2019-12-10 00:37:06 +01:00
982d34815f Update with new sequencer features 2019-12-09 23:40:15 +01:00
07fcd28545 Bump sequencer version to 7.1.0
Update verbose and dry-run handling. Using bash ":" build-in function

Small helpapi update
2019-12-09 23:37:26 +01:00
f514b73322 New option -o for endReturn to directly evaluate an error code
Addition to api help
2019-12-09 14:45:06 +01:00
bf51d0ee11 Bump gitea version to 3.3.4
Rename step update to upgrade

Using correct package for exiftool
2019-12-09 14:42:06 +01:00
3cad9c40c6 Update installation procedure to meet new requirements comming from pyhton3 and mayan-edms 3.3.3+
Switching virtual environment to pyhton3-venv
2019-12-08 21:49:30 +00:00
3d1097bb5d New function step to execute other steps also by alias
Possibilty to skip a step, if run without quiet option

WIP build-in function documentation
2019-12-08 21:38:42 +00:00
4feb26103b Bump gitea version to 1.10.1
Bugfix version
2019-12-06 11:15:06 +01:00
6d12f7aecd Bump mayan version to 3.3.3
supervisor conf working out of the box
2019-12-05 15:13:40 +01:00
0d534be7a9 Bump mayan version to 3.3.2
This major release brought some dependency and syntax updates
2019-12-05 10:43:05 +01:00
30fa3e3551 Bump to version 3.2.11
Wrapping password in " automatically during update or installation using sed
2019-12-01 14:54:37 +01:00
5f662828a2 Security and conformance updates
- Publish abbuse addresse using mod_disco

Allow users to change password with client

- ...
2019-11-23 12:55:41 +01:00
be59c27224 Another use of echoerr 2019-11-23 12:54:16 +01:00
d89dd8e6ab Make use of echoerr to send error messages to stderr 2019-11-22 21:08:05 +01:00
78de3db626 Added list option field to be passed to scp
Usage of echoerr for error messages
2019-11-22 21:07:12 +01:00
aaec21ae93 First functional seq for ssh management
- Installing, Authorization key generation, Authorization key sending, Sending command list

Keys are generated without user input (4096,rsa,comment: hostname,no passphrase,default path)
2019-11-21 23:43:15 +01:00
c7de26455b new function getReturn which return latest value previously saved by saveReturn
function saveReturn returns with the same errno it saved

refactor documentation replace installation with sequence and aborted with stopped

New starting output with absolute path to seq
2019-11-21 23:30:08 +01:00
a2fc9e62c9 Add execution permission 2019-11-20 23:09:53 +01:00
46b6839f50 Started with key creation step 2019-11-20 23:09:29 +01:00
f5193f46ee Bump sequencer revision to 6
Adding optional message for endReturnto replace predefined one
2019-11-20 23:08:44 +01:00
b79ae416e6 WIP for ssh management
Function for parsing a command file, which can send files and execute commands on a given remote host
2019-11-20 16:39:41 +00:00
f5c5120fff Don't show dry-run warning when option quiet is selected 2019-11-20 16:38:23 +00:00
e5678c9692 Fix crash when invalid alias strings contain '.' are processed
Help and commandline informational output
2019-11-20 15:22:02 +00:00
046f80f865 Adding python-sleekxmpp
Dependency for xmpp notification capability.
2019-11-17 23:24:02 +01:00
aafc1cb29c Working seq to install pyload an a raspbian
Tested on raspbian stretch
2019-11-17 00:53:44 +01:00
6a9464f0bb Add step to list mysql users 2019-11-17 00:52:45 +01:00
a5ac79cbcc Bump gitea to 1.10.0 2019-11-15 11:59:17 +01:00
94b3afafe1 Merge branch 'master' of https://winklerfamilie.eu/git/efelon/shell_sequencer 2019-11-13 11:59:44 +01:00
bc12312101 Use dev branch for updates until first release
Add seq to force a cloned repository to dev branch, losing all unstaged changes
2019-11-13 11:59:20 +01:00
dddc133ad4 Initial snmp management seq
Two extends included (raspberry, osupdate)
2019-11-10 11:48:10 +01:00
e8b475d9f7 Add execution rights to sequencer.sh 2019-11-08 09:41:32 +01:00
a9ff5e1478 Adding mysql managment steps listdb and sizedb 2019-11-04 22:41:20 +01:00
a7646beeb0 Bump mayan version to 3.2.9
Include supervisor configuration update and manual editing in update step
2019-11-04 11:45:24 +01:00
49f009a387 Add timestamp to addConf backup 2019-11-04 09:46:26 +00:00
72919548d2 Bump gitea to version 1.9.5; upgrade from 1.9.4 tested successfuly 2019-10-31 15:12:01 +01:00
9a408fa1d4 Update and extend template creation
- Example usage of "exe" and "exep"
- step_1 is not mandatory any more
2019-10-30 13:22:56 +01:00
d206ee1a1d Adding execution rights 2019-10-09 23:52:09 +02:00
a67fb24212 Initial commit with backup functionality 2019-10-09 23:51:35 +02:00
67b785dd49 Added missing exe calls 2019-10-09 23:44:13 +02:00
69740bf6ee Fix using $1 to check if no step was given, although it was shifted
Dry run no longer also assumes -q (quiet) option
2019-10-09 23:43:10 +02:00
519bc7aa92 Do not required step_1 to exist to output step help 2019-10-09 21:37:10 +02:00
a365260995 Minor comment enhancement 2019-10-09 12:09:15 +02:00
c8922f6c6d Add possibility to pass arguments to selected steps (syntax change)
Bump sequencer revision to 5.0.0
2019-10-09 12:07:43 +02:00
9a6901ee95 Automatically backup current gitea binary
Bump to gitea version 1.9.4
2019-10-09 09:45:28 +02:00
f126f9e1df Default php config with max upload 100 MB 2019-10-07 15:49:57 +02:00
844e5040d2 Pump to pixelfed version v0.10.4
Adapting .env for activity pub settings
2019-09-24 13:45:32 +02:00
1ac923c774 Bump php version to 7.3
Adding database backup/restore information
2019-09-24 13:10:18 +02:00
8e370a0e56 Bump gitea version to 1.9.3 2019-09-08 20:51:20 +02:00
e0a3c3d877 Updated to latest generic installation process 2019-09-08 20:46:12 +02:00
9d6e646c3e Bump latest version to 1.9.0 2019-07-31 21:16:12 +02:00
a3a051e38a Bump mayan version to 3.2.6 2019-07-11 08:47:07 +02:00
56ea46c8c7 Bumped supported version to 3.2.4 2019-06-30 13:23:26 +02:00
322eec18f3 Rework usage of mayan-edms.py 2019-06-23 22:23:08 +02:00
50d3b98e0f Bump to latest version
Hide password on entry
2019-06-23 21:09:13 +02:00
ceba5f37c3 Adding update step 2019-06-19 16:15:07 +02:00
57fba73e8a Adding upgrade step 2019-06-19 16:12:27 +02:00
4e8a3ddf9a Fix missing write permissions on storage for http upload
+ Check for missing basic configuration
2019-06-07 09:43:23 +02:00
223b9d7abe New seq for ejabberd on debian 2019-06-06 17:32:46 +02:00
6cb5dc595b Adding postupdate step recommended by documentation
see (https://docs.pixelfed.org/master/deployment.html)
2019-06-05 10:14:17 +02:00
ddbc4657f7 Bump to revision 4
making use of extended functionality of addConf and exep
2019-05-27 15:02:38 +02:00
e37f6269ee Ignoring missingConf.log everywhere 2019-05-27 14:39:05 +02:00
581c3d1ed6 New paramter for addConf (skip backup if exist; only add to missing conf)
Various output text corrections (context dry run and verbose)
2019-05-27 14:25:32 +02:00
48f6de3026 New exep function which handels pipes and redirects properly
rework mayan backup and restore steps
2019-05-26 03:02:12 +02:00
ab10ef6504 Bump to revision 3
addConf with mandatory paramter; suppots appending
2019-05-17 11:59:51 +01:00
34966ddf79 Additions to mayan sequence
file permission update
2019-05-16 19:31:33 +00:00
50e4bf01c4 typo 2019-05-16 13:59:56 +02:00
b6407c172e Making script more flexible
* all postgres settings from user entry (user,pass,db_name)
* tool root as variable
* tool media folder as variable
* data base creation as own step
2019-05-16 13:58:57 +02:00
8413e2d518 Typo in service start 2019-05-14 13:42:40 +02:00
77f8c63276 Download latest version running on rapbian 2019-05-14 13:37:45 +02:00
4e88850aba First working installation with pixelfed sequence
Still some manual work to do
2019-05-12 20:04:34 +00:00
a1528de93e [WIP/notest] pixelfed sequence 2019-05-12 01:07:33 +02:00
310f7d5a1e Postgress password global to be able to set in supervisor config 2019-05-12 01:00:34 +02:00
0be0629bd7 Don't ask for permission to install in step 1 2019-05-12 00:28:55 +02:00
75d30a08d6 WIP mayan edms direct mayan edms deployment 2019-05-11 23:19:42 +02:00
c877566b4e small fix 2019-05-11 23:18:39 +02:00
3b9e4bee89 [WIP] new seqs 2019-05-09 20:28:00 +00:00
9ad3d001d8 small fixes 2019-05-09 20:27:03 +00:00
60bb0cb79a Fixed file permissions (+x) 2019-05-01 12:59:26 +02:00
cb6ee47496 Added missing exe calls and raised sequence revision 2019-04-30 10:29:44 +02:00
600667c25b Adding final configuration notes after last "install" step 2019-04-15 14:55:28 +02:00
eb20953214 First attempt to include dry run functionality 2019-04-10 15:45:33 +01:00
b7edd7d6bc adding database collate comment 2019-04-10 15:01:49 +02:00
98469b1d20 preparation for verbose output of shell commands (called by function exe()) 2019-04-10 12:33:34 +01:00
4c50382428 some fixes and enhancements
preparation for verbose output of commands
2019-04-10 12:32:23 +01:00
3b23840277 support multiple shell arguments (e.g. -v -q)
new verbose output (-v) to echo commands called with exe() before execution
2019-04-10 11:12:28 +01:00
a124608e36 fix addConf call 2019-04-10 08:40:54 +02:00
4516bbb363 fix wget call 2019-04-09 19:43:38 +02:00
2a27608b14 Fix missing config file suffix 2019-04-09 15:15:54 +01:00
9fad2a9121 Major rewrite/cleanup with additional functionality (creating databases) 2019-04-09 11:03:39 +01:00
0789a586d2 Minor cleaning of comments
Bump to SEQREV 2
2019-04-09 11:02:36 +01:00
0f206660a6 New common function to create config files savely 2019-04-09 11:01:09 +01:00
60ee5d776f wip mysql and basic nginx configuration (letsencrypt ready) 2019-04-09 01:30:59 +02:00
ac721ddac6 wip webserver sequence 2019-04-08 22:09:51 +02:00
42aa8def70 New seqs 2019-04-08 14:45:15 +01:00
e6313d2c32 fix #3
Introducing text alias for steps
2019-04-08 14:44:31 +01:00
119 changed files with 13353 additions and 399 deletions

6
.editorconfig Normal file
View File

@@ -0,0 +1,6 @@
root = true
[*.{sh,bash,cfg,example}]
charset = utf-8
indent_style = space
indent_size = 2

4
.gitignore vendored
View File

@@ -1 +1,3 @@
/seqTemplateExample.sh
seqTemplateExample.sh
missingConf.log
*.cfg

View File

@@ -15,6 +15,73 @@ Contains sequences (seqs) for different tools, servers or occasions.
Sequencer include working on sh and bash.
[...]
. ./sequencer.sh
. /usr/local/bin/sequencer.sh
see [seqTemplate.sh](https://winklerfamilie.eu/git/efelon/shell_sequencer/src/branch/master/seqTemplate.sh)
see seqTemplateExample.sh (which can be generated when calling sequencer.sh directly)
## Installation recommendation
To make all seqs avaialable to all user, follow the procedure below.
Run folloing commands as root:
```
git clone https://winklerfamilie.eu/git/efelon/shell_sequencer.git /opt/sequencer
ln -s /opt/sequencer/sequencer/sequencer.sh /usr/local/bin
ln -s /opt/sequencer/seqs /opt
```
or
use the simple bash installation script in the repository which installs git and performs the steps above:
```
curl -L https://winklerfamilie.eu/git/efelon/shell_sequencer/raw/branch/master/install.sh | bash
```
You may override the default installation path `/opt/sequencer` by appending `-s /custom/path` to the command above:
e.g. `curl -L https://winklerfamilie.eu/git/efelon/shell_sequencer/raw/branch/master/install.sh | bash -s /usr/lib/sequencer`
## Bash-completion
The included optional bash-completion script `sqnall-completion.bash` provides aliases to all available sequences as well as completion for sequencer.sh options and steps (including aliases) individually for each sequence. The aliases have the prefix `sqn_` which stands for _sequence name_.
After executing
```
source /opt/sequencer/sqnall-completion.bash
```
e.g. `/opt/sequencer/seqs/kodi.sh` can be started anyhere with `sqn_kodi`
### Custom sequence directory
To control which seqs are available for bash-completion, copy `sequencer.cfg.dist` to `sequencer.cfg` and adjust the value of the variable `SEQUENCER_USER_SEQS`.
To make these changes active run the following commands. You don't need the last step if you already used `installCompletion.sh`.
```
unalias -a
source ~/.bashrc
source /opt/sequencer/sqnall-completion.bash
```
or simply logout from the current session and login again.
### Automatic setup after login
To automatically provide aliases and bash-completion after login, the following bash script needs to be executed once for each user separately:
```
source /opt/sequencer/installCompletion.sh
```
This sources the bash-completion script in the users .bashrc file.
## Default text editor
Sequencer uses the Debian alternatives system to select which editor to use. To change the default editor, which by default is most likely _nano_:
```
update-alternatives --config editor
```

66
install.sh Executable file
View File

@@ -0,0 +1,66 @@
#!/bin/bash
# shellcheck disable=SC1090 # dynamically sourced file
SEQGITURL="https://winklerfamilie.eu/git/efelon/shell_sequencer.git"
DEFAULT_DIR="/opt/sequencer"
DEFAULT_USER_SEQS="/opt/seqs"
SEQUENCER_DIR=
# Get script working directory
WDIR="$(cd "$(dirname -- "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
SEQUENCER_DIR="$1"
# Installation directory was not set by argument -d
if [ -z "$SEQUENCER_DIR" ]; then
[ -w "$(dirname "$DEFAULT_DIR")" ] && SEQUENCER_DIR="$DEFAULT_DIR"
# Fallback to working directory
[ -z "$SEQUENCER_DIR" ] && SEQUENCER_DIR="${WDIR}/sequencer"
fi
# Check if already installed
if [ -d "$SEQUENCER_DIR" ]; then
echo " [E] Sequencer seems to be already installed at:"
echo " $SEQUENCER_DIR"
exit 1
fi
if [ ! -w "$(dirname "$SEQUENCER_DIR")" ]; then
echo " [E] Your user has no permission to write to $(dirname "$SEQUENCER_DIR")"
exit 2
fi
# Install git if neccessary
if ! which git >>/dev/null 2>&1; then
echo " [W] Git not found and will be installed"
if ! apt update; then
echo " [W] Cannot update apt repositories"
fi
if ! apt install git -y; then
echo " [E] Cannot install git via apt"
exit 3
fi
fi
# Clone sequncer to target directory
if ! git clone $SEQGITURL "$SEQUENCER_DIR"; then
echo " [E] Error cloning git repository:"
echo " $SEQGITURL"
exit 4
fi
# If available use configuration
. "${SEQUENCER_DIR}/sequencer.cfg" >/dev/null 2>&1
# Set to default if not configured
[ -z "$SEQUENCER_USER_SEQS" ] && SEQUENCER_USER_SEQS="$DEFAULT_USER_SEQS"
# Install sequncer script
ln -s "${SEQUENCER_DIR}/sequencer/sequencer.sh" "/usr/local/bin"
if [ "$SEQUENCER_USER_SEQS" != "$SEQUENCER_DIR/seqs" ]; then
ln -sT "${SEQUENCER_DIR}/seqs" "${SEQUENCER_USER_SEQS}"
fi
echo " [I] Successfully installed shell sequencer"
echo " to: $SEQUENCER_DIR"

21
installCompletion.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Get script working directory
sq_dir="$(cd "$(dirname -- "$(realpath "${BASH_SOURCE[0]}")")" >>/dev/null 2>&1 && pwd)"
_sequencerCompletion() {
local SEQCOMP_LOC="${sq_dir}/sqn-completion.bash"
local SEQCOMP_LOADER="$HOME/.bashrc"
local SEQCOMP_SOURCE=". \"$SEQCOMP_LOC\""
if grep "$SEQCOMP_SOURCE" "$SEQCOMP_LOADER" >>/dev/null 2>&1; then
echo " [I] Completion already installed ($SEQCOMP_LOADER)"
else
echo "$SEQCOMP_SOURCE" >>"$SEQCOMP_LOADER"
echo " [I] Sequence bash-completion installed"
fi
# shellcheck source=sqn-completion.bash
. "$SEQCOMP_LOC"
}
_sequencerCompletion

View File

@@ -1,46 +0,0 @@
#!/bin/bash
##
## Sequencer interface:
## - step_[1 - 255]_info [STEP NUMBER]
## functions providing short header for help and user interaction
## - step_[1 - 255] [STEP NUMBER]
## functions performing custom operations
##
step_1_info() { echo "Step $1 header"; }
step_1() {
cat .nofile
saveReturn $?
}
step_2_info() { echo "Step $1 header"; }
step_2() {
echo -e "Zwei"
endReturn
echo zwo
}
step_3_info() { echo "Step $1 header"; }
step_3() {
echo drei
}
step_10_info() { echo "Step $1 header"; }
step_10() {
echo zehn
}
step_11_info() { echo "Step $1 header"; }
step_11() {
echo elf
}
# Sequence Revision
VERSION_SEQREV=1
# Workaround when called from different directory
# Not needed when path to sequencer is absolut
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
# Path to local sequencer.sh script
. ${DIR}/./sequencer/sequencer.sh

8
seqs/aria2.cfg.example Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
ARIA2_RPC_SECRET=""
ARIA2_CONF="dir=/var/lib/aria2
file-allocation=none
enable-rpc=true
rpc-secret=$ARIA2_RPC_SECRET
rpc-listen-all=true"

85
seqs/aria2.sh Executable file
View File

@@ -0,0 +1,85 @@
#!/bin/bash
toolName=aria2
toolDeps=aria2
toolUser=aria2
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
CONFIG=0
SCRIPT_NAME=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_NAME%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
aptOpt=
step_config() {
#echo "Called once before executing steps."
## e.g. to source a config file manually:
#. "$CONFIG_FILE"
## or to use sequencer api with global config file:
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
## or to use sequencer api with profile config file support:
#initSeqConfig -p "$SCRIPT_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return 1
fi
[ $QUIET -ne 0 ] && aptOpt="-y"
return 0
}
step_1_info() { echo "Install $toolName"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
exe apt install $toolDeps $aptOpt
}
step_2_info() { echo "Create $toolName configuration"; }
step_2() {
exe adduser --system --quiet "$toolUser"
if [ ! -e $ariaConfLoc ] ; then
exe mkdir -p "$(dirname $ariaConfLoc)"
addConf -s "$ARIA2_CONF" "$ariaConfLoc"
exe chown $toolUser:root "$ariaConfLoc"
exe chmod 770 "$ariaConfLoc"
fi
}
ariaConfLoc="/etc/aria2/aria2.conf"
step_3_info() { echo "Create $toolName service"; }
step_3_alias() { ALIAS="service"; }
step_3() {
addConf -s "$ariaService" "$ariaServiceLoc"
exe systemctl daemon-reload
echoseq " [I] Serive not started or enabled"
}
ariaServiceLoc="/etc/systemd/system/aria2.service"
ariaService="[Unit]
Description=Aria2
After=network-online.target
[Service]
User=$toolUser
Type=forking
ExecStart=/usr/bin/aria2c --conf-path=${ariaConfLoc} --daemon
ExecStop=/bin/kill -s STOP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target"
step_10_info() { echo "Add ufw rule for rpc port 6800"; }
step_10_alias() { ALIAS="ufw"; }
step_10() {
exe ufw allow in on eth0 to any port 6800 proto tcp comment "Aria2 rpc"
}
VERSION_SEQREV=12
. /usr/local/bin/sequencer.sh

25
seqs/backup.cfg.example Normal file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
# Backup sequence definitions
# A running debian needs at least the following runtime directories created to start up successfully:
## dev
## proc
## sys
## run
BACKUP_TARGET="/backup"
# Exclude notation "directory/*" creates the directory but NOT its content
# Leading slash binds the rule to the "root" of the transfer operation
BACKUP_EXCLUDES=(\
"/backup*"\
"/home/network/*"\
"/dev/*"\
"/proc/*"\
"/sys/*"\
"/tmp/*"\
"/run/*"\
"/mnt/*"\
"/media/*"\
"/lost+found"\
)

193
seqs/backup.sh Executable file
View File

@@ -0,0 +1,193 @@
#!/bin/bash
toolName=backup
toolBin=rsync
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
APTOPT=
CONFIG=0
CONFIG_FILE_NAME="${toolName}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig -t "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
echoerr " [E] Check output for errors"
# End if no configuration file exists
[ $DRY -eq 0 ] && return -1
fi
[ $QUIET -ne 0 ] && APTOPT="-y"
return 0
}
step_1_info() {
echoinfoArgs "[ADDITIONAL_EXCLUDES...]"
echo "Backup root"
echoinfo "Essential excludes are provided in the configuration template."
echoinfo "($CONFIG_FILE_TEMPLATE)"
}
step_1_alias() { ALIAS="buroot"; }
step_1() {
local buTarget="/backup"
if [ $CONFIG -eq 0 ] ; then
echoerr " [E] Cannot backup root without properly configured excludes"
echoerr " (expected config: $SEQ_CONFIG_HOME/$CONFIG_FILE_NAME)"
else
buTarget="$BACKUP_TARGET"
fi
# don't use step number
shift
step budir / "$buTarget" "${BACKUP_EXCLUDES[@]}" "$@"
}
step_3_info() {
# Backup single directory recursively
local opt="[OPTION]"
local dir="<DIRECTORY>"
local tar="<TARGET>"
local exc="[EXCLUDES...]"
shift
if [ "$1" == "-t" ] ; then
opt=" -t "
tar=
shift
fi
if [ ! -z "$1" ] ; then
dir="$1"
shift
if [ ! -z $tar ] && [ ! -z "$1" ] ; then
tar="$1"
shift
else
tar="$BACKUP_TARGET"
fi
if [ ! -z "$1" ] ; then
exc="$@"
else
exc="[NO EXCLUDES]"
fi
fi
echo "Backup $opt $dir $tar $exc"
echoinfo " -t : Using configuration value as TARGET"
echoinfo " <DIRECTORY> [EXCLUDES...]"
echoinfo "EXCLUDES path notation starts within $dir"
echoinfo "e.g. to exclude $dir/a:"
echoinfo " $0 budir $dir $tar /a"
}
step_3_alias() { ALIAS="budir"; }
step_3() {
local arg
local configTarget=0
local noRemount=0
local buSource=
local buTarget=
local buExcludes=
local buLog=
# don't use step number
shift
for arg in "$@"; do
case "$1" in
-t)
configTarget=1
shift;;
-n)
noRemount=1
shift;;
esac
done
if [ -z "$1" ] ; then
echoerr " [E] Nothing found to backup $1"
exit 1
fi
buLog=$(basename $1)
if [ "$buLog" == "/" ] ; then
buLog="root"
buSource="$1"
else
# remove trailing slashes
buSource=$(echo "$1" | sed 's:/*$::')
fi
buLog="backup_${buLog}"
shift
if [ $configTarget -ne 0 ] && [ $CONFIG -ne 0 ] ; then
# Taking target from config
buTarget=$(echo "$BACKUP_TARGET" | sed 's:/*$::')
else
if [ -z "$1" ] ; then
echoerr " [E] No valid target found"
exit 1
fi
buTarget=$(echo "$1" | sed 's:/*$::')
shift
fi
if [ ! -d "${buTarget}" ] && [ ! -L "${buTarget}" ]
then
echoerr " [E] Backup target (${buTarget}) doesn't exist"
exit 1
fi
for exclu in "$@"; do
buExcludes+=("--exclude='$exclu'")
done
echoseq " [I] Source : $buSource"
echoseq " [I] Target : $buTarget"
echoseq " [I] Excludes: $@"
#fix doubling trailing slash on verbose output when backing up root
local tmpSource="$buSource/"
local tmpTarget="${buTarget}/$(basename ${buSource})"
if [ "$buSource" == "/" ] ; then
tmpSource="/"
tmpTarget="${buTarget}/"
fi
if [ $noRemount -eq 0 ]; then
# remount target to be writable
exep "mount -o rw,remount '${buTarget}' >>/dev/null 2>&1"
endReturn -o $? "Remount (${buTarget}) to be writable failed"
fi
if [ ! -w "${buTarget}" ] ; then
echoerr " [E] Backup target (${buTarget}) is not writable"
exit 1
fi
checkInstalled
exep "mv -f ${buTarget}/${buLog}0.log /tmp/${buLog}1.log 2>/dev/null"
exep "$toolBin -avxHAX --delete --info=stats2 ${buExcludes[*]} ${tmpSource} ${tmpTarget} > /tmp/${buLog}0.log"
exe mv -f /tmp/${buLog}*.log ${buTarget}
exe sync
exep "mount -o ro,remount '${buTarget}' >>/dev/null 2>&1"
}
step_100_info() { echo "Install $toolBin"; }
step_100_alias() { ALIAS="install"; }
step_100() {
exe apt update
exe apt install $toolBin $APTOPT
}
checkInstalled() {
command -v $toolBin >>/dev/null
if [ $? -ne 0 ] ; then
step install
fi
toolBin="$(command -v $toolBin)"
}
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

81
seqs/basics.sh Executable file
View File

@@ -0,0 +1,81 @@
#!/bin/bash
# Collection of simple setup tasks
# e.g. Ability to send mail (ssmtp)
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
WSUBDIR="${WDIR}/basics"
#step_config() {
# echo "Called once before executing steps."
# echo "e.g. to source a config file:"
# #. "$CONFIG_FILE"
#}
step_10_info() { echo "ssmtp installation"; }
step_10_alias() { ALIAS="ssmtp"; }
step_10() {
exe apt update && apt install "$SSMTP_DEPS"
endReturn -o $? "ssmtp installation failed"
}
SSMTP_DEPS="ssmtp"
step_11_info() { echo "ssmtp setup"; }
step_11_alias() { ALIAS="ssmtpSetup"; }
step_11() {
if [ ! -f "$CONFIG_FILE_SSMTP" ] ; then
echoerr " [E] User config ($CONFIG_FILE_SSMTP) not found"
echoerr " See $CONFIG_FILE_SSMTP_TEMPLATE"
return 1
fi
addConf -c -f "$CONFIG_FILE_SSMTP" "$CONFIG_LOC_SSMTP"
endReturn -o $? "Could not write ssmtp configuration"
if [ ! -f "$CONFIG_FILE_SSMTP_AL" ] ; then
echoerr " [W] User aliases ($CONFIG_FILE_SSMTP_AL) not found"
echoerr " See $CONFIG_FILE_SSMTP_TEMPLATE or modify $CONFIG_LOC_SSMTP_AL directly"
return 1
fi
addConf -c -f "$CONFIG_FILE_SSMTP_AL" "$CONFIG_LOC_SSMTP_AL"
endReturn -o $? "Could not write ssmtp aliases"
}
CONFIG_LOC_SSMTP="/etc/ssmtp/ssmtp.conf"
CONFIG_LOC_SSMTP_AL="/etc/ssmtp/revaliases"
CONFIG_FILE_SSMTP="$WSUBDIR/ssmtp.cfg"
CONFIG_FILE_SSMTP_TEMPLATE="${CONFIG_FILE_SSMTP}.example"
CONFIG_FILE_SSMTP_AL="$WSUBDIR/revaliases.cfg"
CONFIG_FILE_SSMTP_AL_TEMPLATE="${CONFIG_FILE_SSMTP}.example"
step_13_info() {
echo -n "Send test E-Mail to "
if [ -z $2 ] ; then echo "<MAILADDRESS>"; else echo "$2"; fi
}
step_13_alias() { ALIAS="ssmtpTest"; }
step_13() {
if [ ! -z "$2" ] || [ "$2" == "" ] ; then
echoerr " [E] No mailaddress provided"
fi
exep "echo \"Subject: sendmail test\" | sendmail -v $2"
}
step_15_info() { echo "ssmtp help"; }
step_15_alias() { ALIAS="ssmtpHelp"; }
step_15() {
echo " Configuration files expected by this seq:"
echo
echo " - $CONFIG_FILE_SSMTP"
echo " (see template: $CONFIG_FILE_SSMTP_TEMPLATE)"
echo " - $CONFIG_FILE_SSMTP_AL optional"
echo " (see template: $CONFIG_FILE_SSMTP_AL_TEMPLATE)"
echo
echo " ssmtp configuration files"
echo
echo " - $CONFIG_LOC_SSMTP"
echo " - $CONFIG_LOC_SSMTP_AL"
}
VERSION_SEQREV=9
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,6 @@
# sSMTP aliases
#
# Format: local_account:outgoing_address:mailhub
#
# Example: root:your_login@your.domain:mailhub.your.domain[:port]
# where [:port] is an optional port number that defaults to 25.

View File

@@ -0,0 +1,24 @@
#
# Config file for sSMTP sendmail
#
# The person who gets all mail for userids < 1000
# Make this empty to disable rewriting.
root=postmaster
# The place where the mail goes. The actual machine name is required no
# MX records are consulted. Commonly mailhosts are named mail.domain.com
mailhub=host:port
#AuthUser=
#AuthPass=
UseTLS=YES
# Where will the mail seem to come from?
rewriteDomain=mydomain.eu
# The full hostname
hostname=mydomain.eu
# Are users allowed to set their own From: address?
# YES - Allow the user to specify their own From: address
# NO - Use the system generated From: address
#FromLineOverride=YES

View File

@@ -0,0 +1,17 @@
#!/bin/bash
CALWEB_BASE="/opt/calibre-web"
CALWEB_VENV_ROOT="$CALWEB_BASE/venv"
CALWEB_USER_HOME="$CALWEB_BASE/home"
CALWEB_USER="calibreweb"
CALWEB_SERVICE="[Unit]
Description=Calibre-Web
After=network-online.target
[Service]
Type=simple
User=$CALWEB_USER
ExecStart="$CALWEB_VENV_ROOT/bin/cps"
[Install]
WantedBy=multi-user.target"

131
seqs/calibreweb.sh Executable file
View File

@@ -0,0 +1,131 @@
#!/bin/bash
toolName=calibre-web
toolPipName=calibreweb
toolDeps="python3-pip python3-venv"
toolFeatures=( metadata comics )
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
## or to use sequencer api with global config file:
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return -1
fi
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && APTOPT="-y"
## Return of non zero value will abort the sequence
return 0
}
step_1_info() { echo "Install dependencies"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt install $toolDeps $APTOPT
}
step_2_info() { echo "Setup python virtual environment"; }
step_2() {
if ! id $CALWEB_USER &>/dev/null; then
exe adduser --disabled-password --disabled-login --home-dir "$CALWEB_USER_HOME" --gecos "" $CALWEB_USER
exe usermod -aG users $CALWEB_USER
else
echoseq " [W] User $CALWEB_USER already exists"
fi
if [ ! -e "$CALWEB_VENV_ROOT/bin" ]; then
exe python3 -m venv "$CALWEB_VENV_ROOT"
endReturn -o $? "Creating virtual environment failed"
exe chown -R ${CALWEB_USER}: "$CALWEB_BASE"
else
echoseq " [W] Virtual env. $CALWEB_VENV_ROOT already exists"
fi
}
step_3_info() { echo "Install $toolName using pip"; }
step_3() {
step upgradepip
exe ${CALWEB_VENV_ROOT}/bin/pip install $toolPipName
}
step_4_info() {
echo "Install $toolName features"
echoinfo ${toolFeatures[*]}
}
step_4() {
for i in "${!toolFeatures[@]}"; do
toolFeatures[$i]="$toolPipName[${toolFeatures[$i]}]"
done
exe ${CALWEB_VENV_ROOT}/bin/pip install "${toolFeatures[@]}"
}
step_5_info() { echo "Install systemd service"; }
step_5() {
addConf -s "$CALWEB_SERVICE" "$calweb_service_loc"
[ $? -eq 0 ] && exe systemctl daemon-reload
}
calweb_service_name="calibreweb.service"
calweb_service_loc="/etc/systemd/system/$calweb_service_name"
step_6_info() { echo "Enable and start systemd service"; }
step_6() {
exe systemctl enable $calweb_service_name --now
}
step_15_info() { echo "Upgrade python pip"; }
step_15_alias() { ALIAS="upgradepip"; }
step_15()
{
exe ${CALWEB_VENV_ROOT}/bin/pip install --upgrade pip
}
step_100_info() { echo "Setup notes"; }
step_100_alias() { ALIAS="notes"; }
step_100() {
outColor green
cat <<NOTES_END
# Default admin login:
Username: admin
Password: admin123
# nginx reverse proxy
nginx configuration for a local server listening on port 8083:
server {
client_max_body_size 20M;
location / {
proxy_bind \$server_addr;
proxy_pass http://127.0.0.1:8083;
proxy_set_header Host \$http_host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Scheme \$scheme;
}
}
## mapping Calibre-Web to a subfolder /calibre
Change/add the following lines in the configuration above:
location /calibre {
proxy_set_header X-Script-Name /calibre; # IMPORTANT: path has NO trailing slash
NOTES_END
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh

22
seqs/certbot.cfg.example Normal file
View File

@@ -0,0 +1,22 @@
#!/bin/bash
# Web root path where certbot will place the ACME challenge files
#
# A nginx example location which needs to placed in the server config listening on port 80
# for the first time and also in the config listeing on port 443 for renewals:
#
# location ^~ /.well-known/acme-challenge/ {
# default_type "text/plain";
# root /var/www/letsencrypt;
# }
CERTBOT_WEBROOT="/var/www/letsencrypt"
# Email address for important account notifications
CERTBOT_MAIL="postmaster@mydomain.eu"
# Uncomment and list your domains here.
# The first will be the subject CN and all other will be listed as Subject Alternative Names.
#CERTBOT_DOMAINS=(\
# mydomain.eu \
# www.mydomain.eu \
# )

83
seqs/certbot.sh Executable file
View File

@@ -0,0 +1,83 @@
#!/bin/bash
# Certbot installation and creation supporting Raspbian and Ubuntu.
# Certificate can be created/updated as "certonly" only.
toolName=certbot
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="${toolName}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
local confReturn=$?
if [ $confReturn -eq 0 ] ; then
CONFIG=1
fi
}
step_1_info() { echo "Install $toolName for letsencrypt"; }
step_1_alias() { ALIAS="install"; }
step_1() {
local osName=
local distName=
if [ "$(which lsb_release)" == "" ] ; then
echoerr " [W] Cannot detect OS. Assuming Ubuntu"
osName="Ubuntu"
else
osName=$(lsb_release -is)
distName=$(lsb_release -cs)
fi
if [ "$osName" == "" ] ; then
echoerr " [W] Error dedecting OS. Assuming Ubuntu"
osName="Ubuntu"
fi
echo " [I] Detected OS: $osName $distName"
local aptOption=
if [ $QUIET -ne 0 ] ; then
aptOption="-y"
else
aptOption=""
fi
if [ "$osName" == "Ubuntu" ] ; then
exe apt-get update
exe apt-get install software-properties-common $aptOption
saveReturn $?
exe add-apt-repository universe $aptOption
saveReturn $?
exe add-apt-repository ppa:certbot/certbot $aptOption
saveReturn $?
exe apt-get update
exe apt-get install $toolName $aptOption
saveReturn $?
endReturn "$toolName installation for $osName failed"
elif [ "$osName" == "Raspbian" ] ; then
exe apt update
exe apt install certbot
endReturn "$toolName installation for $osName failed"
fi
}
step_2_info() { echo "Create or update letsencrypt certificate"; }
step_2_alias() { ALIAS="update"; }
step_2() {
endCheckEmpty CERTBOT_DOMAINS "No domain list found. Check configuration"
endCheckEmpty CERTBOT_WEBROOT "Invalid web root. Check configuration"
endCheckEmpty CERTBOT_MAIL "Invalid mail address. Check configuration"
exe certbot certonly --webroot -w "$CERTBOT_WEBROOT" --rsa-key-size 4096 --expand --agree-tos \
-m "$CERTBOT_MAIL" ${CERTBOT_DOMAINS[@]/#/-d }
}
VERSION_SEQREV=11
. /usr/local/bin/sequencer.sh

134
seqs/coturn.sh Executable file
View File

@@ -0,0 +1,134 @@
#!/bin/bash
toolName=coturn
toolDeps="coturn miniupnpc"
toolConf="/etc/turnserver.conf"
toolServiceName="coturn.service"
publicIpRetry=20
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
#echo "Called once before executing steps."
## e.g. to source a config file manually:
#. "$CONFIG_FILE"
## or to use sequencer api with global config file:
#initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
## or to use sequencer api with profile config file support:
#initSeqConfig -p "$SCRIPT_NAME" "$CONFIG_FILE_TEMPLATE"
#if [ $? -eq 0 ] ; then
# CONFIG=1
#else
# # End if no configuration file exists
# [ $DRY -eq 0 ] && return -1
#fi
[ $QUIET -ne 0 ] && APTOPT="-y"
return 0
}
step_1_info() { echo "Install $toolName"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
exe apt install $toolDeps $APTOPT
}
step_10_info() {
echo "Update $toolName 'external-ip' using dig [OPTION] [CUSTOM DNS]"
echoinfo " [OPTION]"
echoinfo " -l : Always output update required and error information"
echoinfo " (even with -qq)"
}
step_10_alias() { ALIAS="updateip"; }
step_10() {
exitIfRunning
shift
local retryCount=$publicIpRetry
local ipUpdater
local ipRegex='^[0-2]*[0-9]{1,2}\.[0-2]*[0-9]{1,2}\.[0-2]*[0-9]{1,2}\.[0-2]*[0-9]{1,2}\/*[0-9]*$'
local dnsUrl="46.182.19.48" #digitalcourage.de/support/zensurfreier-dns-server
local dnsFallbackUrl="194.150.168.168" #dns.as250.net; Berlin/Frankfurt
local lecho="echoseq"
if [ "$1" == "-l" ]; then
lecho="echo"
shift
fi
local pubIp
while [ $retryCount -gt 0 ]; do
pubIp=`"$(command -v upnpc)" -s | grep ^ExternalIPAddress | cut -c21-`
[ $? -eq 0 ] && ipUpdater="upnpc" && break || "$lecho" "[$(date)] [W] Upnpc failed"
pubIp=$(dig @$dnsUrl +short +timeout=1 cloud.imoff.de 2>>/dev/null)
[ $? -eq 0 ] && ipUpdater="DNS" && break || "$lecho" "[$(date) [W] DNS lookup to $dnsUrl failed"
pubIp=$(dig @$dnsFallbackUrl +short +timeout=1 cloud.imoff.de 2>>/dev/null)
[ $? -eq 0 ] && ipUpdater="DNS Fallback" && break || "$lecho" "[$(date)] [W] DNS lookup to $dnsFallbackUrl failed"
((retryCount--))
done
if [[ ! $pubIp =~ $ipRegex ]]; then
"$lecho" "[$(date)] [E] Couldn't aquire public IP. Giving up."
return 1
fi
local confIp=`cat "$toolConf" | grep "^external-ip" | cut -d'=' -f2`
if [ "$pubIp" != "$confIp" ]; then
$lecho "[$(date)] [I] Update required (via $ipUpdater). New public ip: $pubIp"
exe sed -i "s/^external-ip[[:space:]]*=.*/external-ip=${pubIp}/" "$toolConf"
exe sleep 1
$lecho "[$(date)] [I] Restarting $toolName"
exe /bin/systemctl restart $toolServiceName
else
echoseq "[$(date)] [I] No update required (via $ipUpdater). Current ip: $confIp"
fi
}
step_12_info() { echo "Setup public ip update cron job every 5 minutes"; }
step_12_alias() { ALIAS="cronip"; }
step_12() {
echoseq " [I] Setup $ipCronLoc"
addConf -s "$ipCron" "$ipCronLoc"
}
ipCronLoc="/etc/cron.d/update_public_ip"
ipCron="*/5 * * * * root $WDIR/$SCRIPT_FILE -qq updateip"
step_100_info() { echo "Installation notes"; }
step_100_alias() { ALIAS="notes"; }
step_100() {
outColor green
cat <<COTURN_EOF
# Port forwarding
3478 tcp/udp
5349 tcp/udp
# Permissions
When using letsencrypt certificates for transport security.
* Add user \`turnserver\` to group \`www-data\`
usermod -aG www-data turnserver
* In the renewal deploy script of cerbot add:
LOC_DOMAIN="yourdoma.in"
chown root:www-data /etc/letsencrypt/archive
chmod 750 /etc/letsencrypt/archive
chown root:www-data /etc/letsencrypt/archive/\$LOC_DOMAIN/privkey*
chmod g+r /etc/letsencrypt/archive/\$LOC_DOMAIN/privkey*
COTURN_EOF
}
VERSION_SEQREV=13
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,6 @@
#!/bin/bash
#CPO = couchpotato
CPO_USER="couchpotato"
CPO_INSTALL_DIR="/var/lib/CouchPotatoServer"

65
seqs/couchpotato.sh Executable file
View File

@@ -0,0 +1,65 @@
#!/bin/bash
toolName=couchpotato
toolDeps="git python-lxml python-pip libssl-dev libffi-dev"
toolGit="https://github.com/CouchPotato/CouchPotatoServer.git"
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_NAME=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_NAME%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
[ $DRY -eq 0 ] && return -1
fi
[ $QUIET -ne 0 ] && APTOPT="-y"
return 0
}
step_1_info() {
echo "Install $toolName"
echoinfo "Default port: 5050"
}
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
exe apt install $toolDeps $APTOPT
exe pip install --upgrade pyopenssl
endReturn -o $? "Pip install pyopenssl failed"
}
step_2_info() { echo "Clone git repository"; }
step_2() {
exe git clone $toolGit "$CPO_INSTALL_DIR"
}
step_3_info() { echo "Create user $toolUser"; }
step_3() {
exe adduser --system --group --home "${CPO_INSTALL_DIR}" --no-create-home "$CPO_USER"
exe chown -R ${CPO_USER}: "${CPO_INSTALL_DIR}"
}
step_4_info() { echo "Create systemd service"; }
step_4() {
exe cp "$CPO_INSTALL_DIR/init/couchpotato.service" "/etc/systemd/system"
endReturn -o $? "Creating service file failed"
exe systemctl daemon-reload
}
step_5_info() { echo "Add ufw rule for web interface"; }
step_5_alias() { ALIAS="ufw"; }
step_5() {
exe ufw allow in on eth0 to any port 5050 proto tcp comment "couchpotato"
}
VERSION_SEQREV=12
. /usr/local/bin/sequencer.sh

300
seqs/debianrpi.sh Executable file
View File

@@ -0,0 +1,300 @@
#!/bin/bash
#toolName=mytool
toolDownSite="https://raspi.debian.net/tested-images"
toolDownUrl=
toolDownFile=
toolEssentialDeps="vim bash-completion man-db locales wget"
SDDEV=
SDBOOT=
SDBOOTPUUID=
SDROOT=
SDROOTDEV=
SDROOTPUUID=
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
APTOPT=
CONFIG=0
SCRIPT_NAME=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_NAME%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
[ $QUIET -ne 0 ] && APTOPT="-y"
return 0
}
step_1_info() {
echo "Download latest xz-compressed image [IMAGE FILE URL] [SD CARD DEVICE]"
echoinfo "$toolDownSite"
}
step_1_alias() { ALIAS="install"; }
step_1() {
shift
SDDEV="$2"
if [ -z "$1" ] && [ $QUIET -eq 0 ] ; then
read -p "Provide image download url from $toolDownSite: " toolDownUrl
elif [ ! -z "$1" ] ; then
toolDownUrl="$1"
else
echoerr " [E] No image file provided for download"
exit 1
fi
toolDownFile="/tmp/${toolDownUrl//*\//}"
local downSha256="${toolDownUrl%.img.xz}.xz.sha256"
local downShaFile="${toolDownFile%.img.xz}.xz.sha256"
echo Url: ${toolDownUrl}
echo Sha256: $downSha256
echo "Files: $toolDownFile"
echo " $downShaFile"
if [ ! -f "$downShaFile" ] ; then
exe wget -O "$downShaFile" "$downSha256"
endReturn -o $? "Error downloading $downShaFile"
fi
if [ ! -f "$toolDownFile" ] ; then
exe wget -O "$toolDownFile" "$toolDownUrl"
endReturn -o $? "Error downloading $downDownFile"
fi
echoseq " [I] Checking SHA256 checksum"
exe cd $(dirname "$toolDownFile")
exe sha256sum -c "$downShaFile" >>/dev/null
endReturn -o $? "SHA256 checksum error"
}
step_2_info() { echo "Write image to device [DEVICE]"; }
step_2() {
shift
if [ -z "$SDDEV" ] ; then
SDDEV="$1"
fi
read_sd_dev "$SDDEV"
# check if device was confirmed
endReturn -o $? "SD card device not found"
echoseq " [I] Writing $(basename "$toolDownFile")"
exep "xzcat \"$toolDownFile\" | dd of=$SDDEV bs=64k oflag=dsync status=progress"
exe sync
}
step_3_info() { echo "Prepare SD card for first run"; }
step_3() {
outColor green
cat <<PREPARE_EOF
[I] Setup static IP
[etc/network/interfaces.d/eth0]
#iface eth0 inet dhcp
iface eth0 inet static
address 192.168.0.38/24
gateway 192.168.0.1
iface eth0 inet6 static
address fd00::38/72
gateway fd00::1/64
[I] Disable ipv6
[etc/sysctl.conf]
net.ipv6.conf.eth0.disable_ipv6 = 1
[I] Setup dns nameserver
[etc/resolv.conf]
nameserver 192.168.0.1
nameserver fd00::1
[I] Setup root ssh access
[etc/ssh/sshd_config]
PermitRootLogin yes
[root/.ssh/authorized_keys]
# Root login only possible with an ssh key
PREPARE_EOF
}
step_10_info() { echo "Essential debian setup"; }
step_10_alias() { ALIAS="setup"; }
step_10() {
if [ -z "$(ls /etc/default | grep raspi)" ] ; then
echoerr " [E] Not on a Raspberry pi"
return 1
fi
exe apt update
exe apt full-upgrade $APTOPT
exe apt install $toolEssentialDeps $APTOPT
}
step_11_info() { echo "Set timezone"; }
step_11() {
exe dpkg-reconfigure tzdata
}
step_12_info() { echo "Setup locales to en_US.UTF-8"; }
step_12() {
local localUs="en_US.UTF-8"
local localUsDefault="$localUs UTF-8"
if [ ! -f "$localesConfigLoc" ] ; then
echoerr " [E] Install packages locales first"
exit 1
fi
exe sed -i "s/#[[:space:]]*\($localUsDefault\)/\1/" "$localesConfigLoc"
endReturn -o $? "Changing locales failed"
exe locale-gen
exe update-locale LANG=$localUs
echoseq " [I] Logout and login for changes to be active"
}
localesConfigLoc="/etc/locale.gen"
step_14_info() { echo "Change hostname [HOSTNAME]"; }
step_14_alias() { ALIAS="hostname"; }
step_14() {
shift
local localHostname=$1
endCheckEmpty localHostname "No hostname provided"
if [ $(grep -r "$localHostname" "$hostsLoc">>/dev/null; echo $?) -eq 0 ] ; then
echoseq " [I] Hostname $localHostname already defined"
return 0
fi
exe hostnamectl set-hostname "$localHostname"
endReturn -o $? "Couldn't set hostname"
exe sed -i "s/^\(127\.0\.0\.1[[:space:]]*\)\(localhost.*\)/\1\2\n\1$localHostname/" "$hostsLoc"
}
hostsLoc="/etc/hosts"
step_16_info() { echo "Install cifs mounting requirements"; }
step_16_alias() { ALIAS="cifs"; }
step_16() {
exe apt install cifs-utils $APTOPT
}
step_17_info() { echo "Cifs notes"; }
step_17() {
outColor green
cat <<CIFS_EOF
# Example fstab entry
[/etc/fstab]
//192.168.0.10/Qdownload /mnt/Qdownload cifs vers=1.0,credentials=/root/.smbpasswd,uid=username,gid=groupname,file_mode=0775,dir_mode=0775 0 0
# Mounting during boot may fail on Rpi4. This changes the entry to automount
(note "_netdev" and "comment=systemd.automount")
//192.168.0.10/Qdownload /mnt/Qdownload cifs _netdev,vers=2.0,credentials=/root/.smbpasswd,uid=username,gid=groupname,file_mode=0775,dir_mode=0775,comment=systemd.automount 0 0
## Alternatively this options were reported to work
auto,x-systemd.automount
# Example .smbpasswd
Don't forget to chown 600 this file.
[/root/.smbpasswd]
username=REMOTEUSER
password=REMOTEPASSWORD
CIFS_EOF
}
step_19_info() { echo "Setup notes"; }
step_19_alias() { ALIAS="setupnotes"; }
step_19() {
outColor green
cat <<SETUPNOTES_EOF
# Secure root with a password
passwd
# Create a regular user
adduser USERNAME
SETUPNOTES_EOF
}
step_40_info() { echo "Boot from HD notes"; }
step_40_alias() { ALIAS="hdboot"; }
step_40() {
outColor green
cat <<HDBOOT_EOF
[I] Raspberry pi 4 boots from USB automatically if there is no SD available
(needs boot loader version September 3rd)
[I] Adding a swap partition
* [RASPIROOTSSD/etc/fstab]
LABEL=RASPISWAP none swap sw 0 3
* Debian enables a swap partition automatically
because by default there is no swap file
[I] Procedure for raspi 3 is similar to the one for raspbian
(boot on SD and root on SSD)
* Clone RAPSIROOT from SD to SSD
rsync -axHAX RASPIROOT/ RASPIROOTSSD/
* [/boot/firmware/cmdline.txt]
root=LABEL=RASPIROOTSSD
* [RASPIROOTSSD/etc/fstab]
LABEL=RASPIROOTSSD / ...
HDBOOT_EOF
}
read_sd_dev() {
local partExt=""
if [ ! -z "$1" ] ; then
SDBOOT=
SDROOT=
SDROOTDEV=
SDROOTPUUID=
SDBOOTPUUID=
SDDEV="$1"
elif [ -z $SDDEV ] || [ ! -b "$SDDEV" ] ; then
SDDEV=
SDBOOT=
SDROOT=
SDROOTDEV=
SDBOOTPUUID=
SDROOTPUUID=
echo " [I] Available devices:"
echo
exe lsblk -p
echo
exe read -p "Provide SD card device (e.g. /dev/sdb): " SDDEV
fi
if [ ! -b "$SDDEV" ] ; then
echoerr " [I] $SDDEV not a block device"
SDDEV=
return 1
fi
if [[ "$SDDEV" =~ .*blk.* ]] ; then
partExt="p"
fi
if [ -z $SDBOOT ] ; then
SDBOOT=$(findmnt -no TARGET "${SDDEV}${partExt}${SDBOOTPARTNO}")
fi
if [ -z $SDBOOTPUUID ] ; then
IFS=\" read -r _ vPARTUUID _ < <(blkid "${SDDEV}${partExt}${SDBOOTPARTNO}" -s PARTUUID)
SDBOOTPUUID=$vPARTUUID
fi
SDROOTDEV=${SDDEV}${partExt}${SDROOTPARTNO}
if [ -z $SDROOT ] ; then
SDROOT=$(findmnt -no TARGET "${SDROOTDEV}")
fi
if [ -z $SDROOTPUUID ] ; then
SDROOTPUUID=$(findmnt -no PARTUUID "${SDROOTDEV}")
fi
return 0
}
SDBOOTPARTNO=1
SDROOTPARTNO=2
VERSION_SEQREV=12
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,5 @@
#!/bin/bash
DLD_USER="dluser"
DLD_DIR="/opt/downloaders"
DLD_CONFDIR="/opt/downloaders.conf"

617
seqs/downloader.sh Executable file
View File

@@ -0,0 +1,617 @@
#!/bin/bash
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_NAME=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_NAME%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
checkVpn
initSeqConfig -t "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return -1
fi
[ $QUIET -ne 0 ] && APTOPT="-y"
return 0
}
step_1_info() { echo "Install mono"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt install apt-transport-https dirmngr gnupg ca-certificates
exe apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
exep "echo \"deb https://download.mono-project.com/repo/debian stable-buster main\" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list"
exe apt update
# This will apparently be managed by the installation of sonarr later
# (https://sonarr.tv/#downloads-v3-linux Chapter 1)
#exe apt install mono-complete
}
step_2_info() { echo "Install mediainfo"; }
step_2() {
exe wget https://mediaarea.net/repo/deb/repo-mediaarea_1.0-16_all.deb -O /tmp/repo-mediaarea_all.deb
exe dpkg -i /tmp/repo-mediaarea_all.deb
exe apt update
exe apt install mediainfo
}
step_3_info() { echo "Add system user"; }
step_3() {
exe adduser --system $DLD_USER --group --home "${DLD_CONFDIR}"
}
step_4_info() {
echo "Install sonarr"
echoinfo "Default port: 8989"
}
step_4() {
exe apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 2009837CBFFD68F45BC180471F4F90DE2A9B4BF8
exep "echo \"deb https://apt.sonarr.tv/debian buster main\" | tee /etc/apt/sources.list.d/sonarr.list"
exe apt update
exe apt install sonarr
# Start of sonar must be managed by VPN service
exe service sonarr stop
exe systemctl disable sonarr
}
step_5_info() {
echo "Install radarr for arm64"
echoinfo "Default port: 7878"
}
step_5() {
# nightly https://radarr.servarr.com/v1/update/nightly/updatefile?os=linux&runtime=netcore&arch=arm64
# develop https://radarr.servarr.com/v1/update/develop/updatefile?os=linux&runtime=netcore&arch=arm64
exe curl -sL "https://radarr.servarr.com/v1/update/master/updatefile?os=linux&runtime=netcore&arch=arm64" \
-o /tmp/Radarr.tgz
exe tar xvzf /tmp/Radarr.tgz -C "${DLD_DIR}/"
exe mv ${DLD_DIR}/Radarr "${DLD_DIR}/radarr"
exe chown -R ${DLD_USER}:${DLD_USER} "${DLD_DIR}/radarr"
}
step_6_info() { echo "Create radarr service"; }
step_6() {
local radarrConf="${DLD_CONFDIR}/radarr"
local radarrServiceLoc="/etc/systemd/system/radarr.service"
exe mkdir -p "$radarrConf"
exe chown -R $DLD_USER: "$radarrConf"
addConf -s "$radarrService" "$radarrServiceLoc"
exe systemctl daemon-reload
}
radarrService="[Unit]
Description=Radarr Daemon
After=syslog.target network.target
Wants=transmission.service jackett.service nzbget.service
StartLimitIntervalSec=0
[Service]
User=\$DLD_USER
Group=\$DLD_USER
Type=simple
ExecStart=\${DLD_DIR}/radarr/Radarr -nobrowser -data=\$radarrConf
TimeoutStopSec=20
KillMode=process
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Alias=radarr.service"
step_7_info() {
echo "Install jackett for arm64"
echoinfo "Default port: 9117"
}
step_7() {
local jTar="/tmp/Jackett.tgz"
local jUrl="https://github.com/Jackett/Jackett/releases/latest/download/Jackett.Binaries.LinuxARM64.tar.gz"
[ ! -e "$jTar" ] && exe curl -sL "$jUrl" -o "$jTar"
exe tar xvzf "$jTar" -C "${DLD_DIR}"
exe mv "${DLD_DIR}/Jackett" "${DLD_DIR}/jackett"
exe chown -R ${DLD_USER}:${DLD_USER} "${DLD_DIR}/jackett"
}
step_8_info() { echo "Create jackett service"; }
step_8() {
local jackettServiceLoc="/etc/systemd/system/jackett.service"
local lService=`eval "echo \"$jackettService\""`
addConf -s "$lService" "$jackettServiceLoc"
exe systemctl daemon-reload
}
jackettService="[Unit]
Description=Jackett Daemon
After=syslog.target network.target
StartLimitIntervalSec=0
[Service]
User=\$DLD_USER
Group=\$DLD_USER
Type=simple
SyslogIdentifier=jackett
Restart=on-failure
RestartSec=5
WorkingDirectory=\${DLD_DIR}/jackett
ExecStart=/bin/sh \${DLD_DIR}/jackett/jackett_launcher.sh
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
Alias=jackett.service"
step_9_info() {
echo "Install NZBGet for arm64"
echoinfo "Default port: 6789"
}
step_9() {
exe wget -q https://nzbget.net/download/nzbget-latest-bin-linux.run -O /tmp/nzbget-latest-bin-linux.run
# you can skip --arch aarch64 to auto-detect the architecture
exe sh /tmp/nzbget-latest-bin-linux.run --destdir "${DLD_DIR}/nzbget" --arch aarch64
exe chown -R ${DLD_USER}:${DLD_USER} "${DLD_DIR}/nzbget"
}
step_10_info() { echo "Create NZBGet service"; }
step_10() {
local nzbServiceLoc="/etc/systemd/system/nzbget.service"
local lService=`eval "echo \"$nzbService\""`
local nzbConfOri="${DLD_DIR}/nzbget/nzbget.conf"
local nzbConf="${DLD_CONFDIR}/nzbget/nzbget.conf"
exe mkdir -p "$(dirname "$nzbConf")"
exe chown -R $DLD_USER: "$(dirname "$nzbConf")"/..
addConf -s "$lService" "$nzbServiceLoc"
exe systemctl daemon-reload
exe cp -n "$nzbConfOri" "$nzbConf"
}
nzbService="[Unit]
Description=NZBGet Daemon
After=syslog.target network.target
StartLimitIntervalSec=0
[Service]
# Change the user and group variables here.
User=\$DLD_USER
Group=\$DLD_USER
Type=forking
# Pass any command line arguments etc.
ExecStart=\${DLD_DIR}/nzbget/nzbget -D -c \${DLD_CONFDIR}/nzbget/nzbget.conf
ExecStop=\${DLD_DIR}/nzbget/nzbget -Q -c \${DLD_CONFDIR}/nzbget/nzbget.conf
ExecReload=\${DLD_DIR}/nzbget/nzbget -O -c \${DLD_CONFDIR}/nzbget/nzbget.conf
TimeoutStopSec=20
KillMode=process
Restart=on-failure
RestartSec=5
# Sandboxing ... (see https://www.freedesktop.org/software/systemd/man/systemd.exec.html for more info)
ReadWritePaths=\${DLD_DIR}/nzbget \${DLD_CONFDIR}/nzbget /mnt
ProtectSystem=strict
PrivateDevices=true
ProtectHome=true
[Install]
WantedBy=multi-user.target sonarr.service radarr.service
Alias=nzbget.service
#RequiredBy=sonarr.service radarr.service"
step_11_info() {
echo "Install lidarr for arm64"
echoinfo "Default port: 8686"
}
step_11() {
local lidarrDeps="libchromaprint-tools"
local lidarrUrl="https://lidarr.servarr.com/v1/update/develop/updatefile?os=linux&runtime=netcore&arch=arm64"
exe curl -sL "$lidarrUrl" -o /tmp/Lidarr.tgz
endReturn -o "Download failed"
exe apt install $lidarrDeps $APTOPT
exe tar xvzf /tmp/Lidarr.tgz -C "${DLD_DIR}/"
exe mv "${DLD_DIR}/Lidarr" "${DLD_DIR}/lidarr"
exe chown -R ${DLD_USER}:${DLD_USER} "${DLD_DIR}/lidarr"
}
step_12_info() { echo "Create lidarr service"; }
step_12() {
local lidarrConf="${DLD_CONFDIR}/lidarr"
local lidarrServiceLoc="/etc/systemd/system/lidarr.service"
local lService=`eval "echo \"$lidarrService\""`
exe mkdir -p "$lidarrConf"
exe chown -R $DLD_USER: "$lidarrConf"
addConf -s "$lService" "$lidarrServiceLoc"
exe systemctl daemon-reload
}
lidarrService="[Unit]
Description=Lidarr Daemon
After=syslog.target network.target
Wants=transmission.service jackett.service nzbget.service
StartLimitIntervalSec=0
[Service]
User=\$DLD_USER
Group=\$DLD_USER
Type=simple
ExecStart=\${DLD_DIR}/lidarr/Lidarr -nobrowser -data=\$lidarrConf
TimeoutStopSec=20
KillMode=process
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Alias=lidarr.service"
step_13_info() { echo "Install bazarr dependencies"; }
step_13() {
local bazarrDeps="python3-pip python3-distutils python3-venv ffmpeg"
#local bazarrDeps+=" libxml2-dev libxslt1-dev python3-libxml2 python3-lxml libatlas-base-dev"
exe apt install $bazarrDeps $APTOPT
}
step_14_info() { echo "Install bazarr"; }
step_14() {
local bazarrServiceLoc="/etc/systemd/system/bazarr.service"
local lService=`eval "echo \"$bazarrService\""`
local bazarrVenv="${DLD_DIR}/bazarr"
local bazarrDir="${bazarrVenv}/bazarr"
local bazarrGitUrl="https://github.com/morpheus65535/bazarr.git"
exe python3 -m venv "$bazarrVenv"
endReturn -o $? "Creating virtual environment failed"
exe git clone $bazarrGitUrl "$bazarrDir"
exe chown -R $DLD_USER: "$bazarrVenv"
exe sudo -u $DLD_USER ${bazarrVenv}/bin/pip install --upgrade pip
exe sudo -u $DLD_USER ${bazarrVenv}/bin/pip install -r ${bazarrDir}/requirements.txt
addConf -s "$lService" "$bazarrServiceLoc"
exe systemctl daemon-reload
}
bazarrService="[Unit]
Description=Bazarr
After=syslog.target network.target
Wants=sonarr.service radarr.service
StartLimitIntervalSec=0
[Service]
User=\$DLD_USER
Group=\$DLD_USER
Type=simple
ExecStart=\${DLD_DIR}/bazarr/bin/python3 \${DLD_DIR}/bazarr/bazarr/bazarr.py
TimeoutStopSec=20
#KillMode=process
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Alias=bazarr.service"
step_15_info() { echo "Create ufw rules for default ports"; }
step_15_alias() { ALIAS="ufw"; }
step_15() {
exe ufw allow in on eth0 to any port 6789 proto tcp comment "NZBGet"
exe ufw allow in on eth0 to any port 9117 proto tcp comment "Jackett. Rules for Sonarr und Radarr in /etc/ufw/rules.before"
outColor red
echo
echo "[W] Add the following lines before \"# drop INVALID packets\""
echo " [/etc/ufw/before.rules]"
echo
outColor green
echo "# Allow all packages to sonarr and radarr"
echo "# ufw thinks that nzb360 sends messages after socket is closed"
echo "-A ufw-before-input -i eth0 -p tcp --dport 7878 -j ACCEPT"
echo "-A ufw-before-input -i eth0 -p tcp --dport 8989 -j ACCEPT"
echo "-A ufw-before-output -o eth0 -p tcp --sport 7878 -j ACCEPT"
echo "-A ufw-before-output -o eth0 -p tcp --sport 8989 -j ACCEPT"
echo
}
step_16_info() {
echo "Build and install unrar-nonfree"
echoinfo "Please provide a deb-src sources entry first"
echoinfo "[/etc/apt/sources.list]"
}
step_16() {
local buildPath="/tmp/unrarbuild"
cat /etc/apt/sources.list | grep -E "^deb-src" >>/dev/null 2>&1
endReturn -o $? "No deb-src entry found in /etc/apt/sources.list"
exe mkdir -p "$buildPath"
exe cd "$buildPath"
exe apt build-dep unrar-nonfree $APTOPT
exe apt source -b unrar-nonfree $APTOPT
endReturn -o $? "unrar-nonfree build failed ($buildPath left untouched)"
exe dpkg -i unrar*.deb
endReturn -o $? "unrar-nonfree install failed ($buildPath left untouched)"
exe rm -rf "$buildPath"
}
step_17_info() { echo "Install danted socks proxy"; }
step_17_alias() { ALIAS="danted"; }
step_17() {
systemctl status danted.service >>/dev/null 2>&1
if [ $? -eq 0 ]; then
echoseq " [I] Danted already installed"
return 0
fi
exe apt update
exe apt install dante-server $APTOPT
exe systemctl stop danted.service
exe systemctl disable danted.service
}
step_18_info() { echo "Danted installation notes"; }
step_18() {
cat <<DANTED_EOF
[I] Debian fix systemd startup
systemctl edit --full danted.service
# Change /lib64 to -/lib64
ReadOnlyDirectories=/bin /etc /lib -/lib64 /sbin /usr /var
[I] Basic danted settings
* Restrict to local network
* Separate logfile
[/etc/danted.conf]
logoutput: stderr /var/log/dante.log
internal: eth0 port = 1080
external: tun0
socksmethod: none
clientmethod: none
client pass {
from: 192.168.0.0/24 port 1-65535 to: 0.0.0.0/0
log: error
}
client block {
from: 0.0.0.0/0 to: 0.0.0.0/0
log: error
}
socks block {
from: 0.0.0.0/0 to: 127.0.0.0/4
log: error
}
socks pass {
from: 192.168.23.0/24 to: 0.0.0.0/0
protocol: tcp udp
log: error
}
socks block {
from: 0.0.0.0/0 to: 0.0.0.0/0
log: connect error
}
DANTED_EOF
}
step_19_info() { echo "Disable apt-daily activities"; }
step_19_alias() { ALIAS="aptdaily"; }
step_19() {
exe /usr/bin/systemctl stop apt-daily-upgrade.timer
exe /usr/bin/systemctl stop apt-daily.timer
exe /usr/bin/systemctl disable apt-daily-upgrade.timer
exe /usr/bin/systemctl disable apt-daily.timer
exe /usr/bin/systemctl mask apt-daily.service
exe /usr/bin/systemctl daemon-reload
}
step_21_info() {
local pInstallDir="${DLD_DIR}/prowlarr"
case $CONTEXT_HELP in
0)
if [ -e "$pInstallDir" ]; then
echo -n "Upgrade "
else
echo -n "Install "
fi
;;
*)
echo -n "Install/Update ";;
esac
echo "prowlarr for arm64"
echoinfo "Default port: 9696"
}
step_21_alias() { ALIAS="prowlarr"; }
step_21() {
# local pDownDir="/tmp"
local pInstallDir="${DLD_DIR}/prowlarr"
local pUrl="http://prowlarr.servarr.com/v1/update/develop/updatefile?os=linux&runtime=netcore&arch=arm64"
[ ! -e "$pTar" ] && exe wget --content-disposition "$pUrl" -O "$pTar"
if [ -e "$pInstallDir" ]; then
prowlarrUpgrade=1
echoseq " [I] Stopping prowlarr service"
echoseq " Service will not be started automatically after update"
exe service prowlarr stop
echoseq " [I] Moving existing $pInstallDir as backup"
exe mv "$pInstallDir" "${pInstallDir}_bu_"`date +%Y%m%d-%H%M%S`
fi
exe tar xvzf "$pTar" -C "${DLD_DIR}"
exe mv "${DLD_DIR}/Prowlarr" "${DLD_DIR}/prowlarr"
exe chown -R ${DLD_USER}:${DLD_USER} "${DLD_DIR}/prowlarr"
}
pTar="/tmp/Prowlarr.tgz"
prowlarrUpgrade=0
step_22_info() { echo "Clean prowlarr download"; }
step_22_alias() { ALIAS="prowlarrclean"; }
step_22() {
exe rm -rf "$pTar"
if [ $prowlarrUpgrade -ne 0 ]; then
echoseq " [I] Stopping sequence here."
echoseq " Following steps only exected for fresh installation."
exit 0
fi
}
step_23_info() { echo "Create prowlarr service"; }
step_23() {
local prowlarrServiceLoc="/etc/systemd/system/prowlarr.service"
local lService=`eval "echo \"$prowlarrService\""`
addConf -s "$lService" "$prowlarrServiceLoc"
exe systemctl daemon-reload
}
prowlarrService="[Unit]
Description=Prowlarr Daemon
After=syslog.target network.target
[Service]
User=\$DLD_USER
Group=\$DLD_USER
Type=simple
SyslogIdentifier=prowlarr
Restart=on-failure
RestartSec=5
WorkingDirectory=\${DLD_DIR}/prowlarr
ExecStart=/bin/sh \${DLD_DIR}/prowlarr/Prowlarr -nobrowser -data=\${DLD_CONFDIR}/prowlarr
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
Alias=prowlarr.service"
step_24_info() { echo "Create ufw rule for prowlarr"; }
step_24() {
exe ufw allow in on eth0 to any port 9696 proto tcp comment "Prowlarr"
}
step_30_info() {
local pInstallDir="${DLD_DIR}/readarr"
case $CONTEXT_HELP in
0)
if [ -e "$pInstallDir" ]; then
echo -n "Upgrade "
else
echo -n "Install "
fi
;;
*)
echo -n "Install/Update ";;
esac
echo "readarr for arm64"
echoinfo "Default port: 8787"
}
step_30_alias() { ALIAS="readarr"; }
step_30() {
# local pDownDir="/tmp"
local lInstallDir="${DLD_DIR}/readarr"
local lUrl="http://readarr.servarr.com/v1/update/nightly/updatefile?os=linux&runtime=netcore&arch=arm64"
[ ! -e "$readarrTar" ] && exe wget --content-disposition "$lUrl" -O "$readarrTar"
if [ -e "$lInstallDir" ]; then
readarrUpgrade=1
echoseq " [I] Stopping readarr service"
echoseq " Service will not be started automatically after update"
exe service readarr stop
echoseq " [I] Moving existing $lInstallDir as backup"
exe mv "$lInstallDir" "${lInstallDir}_bu_"`date +%Y%m%d-%H%M%S`
fi
exe tar xvf "$readarrTar" -C "${DLD_DIR}"
exe mv "${DLD_DIR}/Readarr" "${lInstallDir}"
exe chown -R ${DLD_USER}:${DLD_USER} "${lInstallDir}"
}
readarrTar="/tmp/Readarr.tar.gz"
readarrUpgrade=0
step_31_info() { echo "Clean readarr download"; }
step_31_alias() { ALIAS="readarrclean"; }
step_31() {
exe rm -rf "$readarrTar"
if [ $readarrUpgrade -ne 0 ]; then
echoseq " [I] Stopping sequence here."
echoseq " Following steps only exected for fresh installation."
exit 0
fi
}
step_32_info() { echo "Create readarr service"; }
step_32() {
local readarrServiceLoc="/etc/systemd/system/readarr.service"
local lService=`eval "echo \"$readarrService\""`
addConf -s "$lService" "$readarrServiceLoc"
exe systemctl daemon-reload
}
readarrService="[Unit]
Description=Readarr Daemon
After=syslog.target network.target
[Service]
User=\$DLD_USER
Group=\$DLD_USER
Type=simple
SyslogIdentifier=readarr
RestartSec=5
WorkingDirectory=\${DLD_DIR}/readarr
ExecStart=\${DLD_DIR}/readarr/Readarr -nobrowser -data=\${DLD_CONFDIR}/readarr
TimeoutStopSec=20
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
Alias=readarr.service"
step_33_info() { echo "Create ufw rule for readarr"; }
step_33() {
exe ufw allow in on eth0 to any port 8787 proto tcp comment "Readarr"
}
step_50_info() { echo "Upgrade bazarr"; }
step_50_alias() { ALIAS="upgradebazarr"; }
step_50() {
local bazarrServiceLoc="/etc/systemd/system/bazarr.service"
local lService=`eval "echo \"$bazarrService\""`
local bazarrVenv="${DLD_DIR}/bazarr"
local bazarrDir="${bazarrVenv}/bazarr"
local bazarrGitUrl="https://github.com/morpheus65535/bazarr.git"
exe sudo -u $DLD_USER ${bazarrVenv}/bin/pip install --upgrade pip
exe sudo -u $DLD_USER ${bazarrVenv}/bin/pip install -r ${bazarrDir}/requirements.txt
}
checkVpn() {
ip -br a | grep tun >>/dev/null 2>&1
[ $? -eq 0 ] && echoseq " [W] A VPN connection is possibly active. Consider deactivating it befor any apt operation."
}
VERSION_SEQREV=13
. /usr/local/bin/sequencer.sh

85
seqs/ebackup.cfg.example Normal file
View File

@@ -0,0 +1,85 @@
#!/bin/bash
# Passphrase for symmetrical(default) or asymmetrical encryption
EBU_PASSPHRASE=
# scheme://[user[:password]@]host[:port]/[/]path
# e.g.
# file://[relative|/absolute]/local/path
# scp://user[:password]@other.host[:port]/[relative|/absolute]_path
# webdav[s]://user[:password]@other.host[:port]/some_dir
# alternatively try lftp+webdav[s]://
EBU_TARGET_USER=
EBU_TARGET_PASS=
EBU_TARGET=
# base directory to backup
EBU_SOURCE=
# Change the volume size to number MB. Default is 200MB.
#EBU_VOLSIZE=
# a command that runs duplicity e.g.
# shape bandwidth use via trickle
# "trickle -s -u 640 -d 5120" # 5Mb up, 40Mb down"
#EBU_PRECMD=""
# How often the backup job should be run
# Default is to run every day at 02:01 am
# (see man 5 crontab for syntax help)
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# m h dom mon dow usercommand
#EBU_CRONTIME='1 2 * * *'
# Uncomment to save the output of the cron run to a logfile
# log file name will be "encBackup_profilename.log"
#EBU_LOG_DIR='/var/log'
# Uncomment to log a message to syslog after
# * backup run
# * cron file update
#EBU_SYSLOG=true
#
## Age options
# activates duplicity --full-if-older-than option (since duplicity v0.4.4.RC3)
# forces a full backup if last full backup reaches a specified age
# (see duplicity man page, chapter TIME_FORMATS)
#EBU_MAX_FULLBKP_AGE=1M
#
## Purge options
# Time frame for old backups to keep "remove-older-than"
# (see duplicity man page, chapter TIME_FORMATS)
#EBU_MAX_AGE=3M
# Number of full backups to keep.
# (see duplicity man page, action "remove-all-but-n-full")
#EBU_MAX_FULL_BACKUPS=1
# Number of full backups for which incrementals will be kept for.
# (see duplicity man page, action "remove-all-inc-of-but-n-full")
#EBU_MAX_FULLS_WITH_INCRS=1
#
## Exclusion options
# Standard excludes when backing up a full system
EBU_EXCLUDES=(\
"/backup*"\
"/dev/*"\
"/proc/*"\
"/sys/*"\
"/tmp/*"\
"/run/*"\
"/mnt/*"\
"/media/*"\
"/lost+found"\
)

330
seqs/ebackup.sh Executable file
View File

@@ -0,0 +1,330 @@
#!/bin/bash
toolName=duplicity
toolBin=
toolPpa="ppa:duplicity-team/duplicity-release-git"
toolCronDir="/etc/cron.d"
toolPrefix="encBackup_"
toolSyslogTag=
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd )"
CONFIG=0
SCRIPT_NAME=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_NAME%%.*}
CONFIG_FILE_TEMPLATE="$WDIR/${SCRIPT_NAME}.cfg.example"
step_config() {
initSeqConfig -p "$SCRIPT_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
[ $DRY -eq 0 ] && return 1
fi
toolSyslogTag="${SCRIPT_NAME}-$SEQ_PROFILE_NAME"
}
step_1_info() {
echo -n "Backup "
if [ $CONTEXT_HELP -ne 0 ] ; then
echo -n "selected profile"
else
echo -n "profile: $SEQ_PROFILE_NAME"
fi
echo " [OPTIONS] [full|incremental]"
echoinfo " [OPTIONS]"
echoinfo " --no-purge, -n : Do not purge old backups after backup"
}
step_1_alias() { ALIAS="backup"; }
step_1() {
shift
local arg
local retVal
local dupArgs
local purgeAfter=1
for arg in "$@" ; do
case "$1" in
--no-purge|-n)
purgeAfter=0
shift
;;
esac
done
if [ -z $EBU_TARGET ] || [ -z $EBU_SOURCE ] ; then
echo " [I] Nothing to do. Check $SEQ_CONFIG_FILE"
return 1
fi
if [ ! -z "$1" ] && ( [ "$1" == "full" ] || [ "$1" == "incremental" ] ) ; then
dupArgs+=("$1")
elif [ ! -z "$1" ] ; then
echo " [W] $toolName command \"$1\" not recognized"
return 1
fi
echo " [I] Running backup profile [$SEQ_PROFILE_NAME]"
if [ "${dupArgs[0]}" != "full" ] && [ ! -z "$EBU_MAX_FULLBKP_AGE" ] ; then
dupArgs+=(--full-if-older-than "$EBU_MAX_FULLBKP_AGE")
fi
if [ ! -z "$EBU_VOLSIZE" ] ; then
dupArgs+=(--volsize "$EBU_VOLSIZE")
fi
checkInstalled
setPassphrase
exe $toolBin "${dupArgs[@]}" "$EBU_SOURCE" "$EBU_TARGET"
retVal=$?
unsetPassphrase
syslogEntry "Backup complete [$retVal]"
if [ $purgeAfter -ne 0 ] ; then
step purge
fi
}
step_3_info() { echo "Verify selected backup"; }
step_3_alias() { ALIAS="verify"; }
step_3() {
shift
if [ -z $EBU_TARGET ] || [ -z $EBU_SOURCE ] ; then
echo " [I] Nothing to do. Check $SEQ_CONFIG_FILE"
return 1
fi
checkInstalled
setPassphrase
exe $toolBin verify "$EBU_TARGET" "$EBU_SOURCE"
unsetPassphrase
}
step_5_info() {
echo "Restore [OPTIONS] <LOCAL TARGET> [TARGET]"
echoinfo " [OPTIONS]"
echoinfo " --file-to-restore, -f <RELPATH> : Relative path within backup"
echoinfo " (file or folder)"
echoinfo " --time, -t <TIME> : Age of file to be restored"
}
step_5_alias() { ALIAS="restore"; }
step_5() {
shift
local arg
local restoreOpt
for arg in "$@" ; do
case "$1" in
--file-to-restore|-f)
shift
restoreOpt+=(--file-to-restore "$1")
shift
;;
--time|-t)
shift
restoreOpt=(-t "$1")
shift
;;
esac
done
if [ -z "$1" ] ; then
echoerr " [E] No target provided"
return 1
fi
local ebuLocalTarget="$1"
local ebuTarget="$EBU_TARGET"
if [ ! -z "$2" ] ; then
ebuTarget="$2"
fi
checkInstalled
setPassphrase
exe $toolBin restore "${restoreOpt[@]}" "$EBU_TARGET" "$ebuLocalTarget"
unsetPassphrase
}
step_7_info() { echo "Purge old backups [TARGET]"; }
step_7_alias() { ALIAS="purge"; }
step_7() {
shift
local ebuTarget="$EBU_TARGET"
local dupCommand=
if [ ! -z "$1" ] ; then
ebuTarget="$1"
fi
if [ ! -z "$EBU_MAX_AGE" ] ; then
dupCommand+="remove-older-than $EBU_MAX_AGE "
elif [ ! -z "$EBU_MAX_FULL_BACKUPS" ] ; then
dupCommand+="remove-all-but-n-full $EBU_MAX_FULL_BACKUPS "
elif [ ! -z "$EBU_MAX_FULLS_WITH_INCRS" ] ; then
dupCommand+="remove-all-inc-of-but-n-full $EBU_MAX_FULLS_WITH_INCRS "
else
if [ $QUIET -eq 0 ] ; then echoerr " [W] No purge option configured" ; fi
return 1
fi
checkInstalled
setPassphrase
exe $toolBin $dupCommand --force "$ebuTarget"
unsetPassphrase
}
step_20_info() {
shift
local ebuTarget=$EBU_TARGET
[ ! -z "$1" ] && ebuTarget="$1"
if [ $CONTEXT_HELP -ne 0 ]; then
echo "Status of (profile) [TARGET]"
elif [ ! -z "$1" ]; then
echo "Status of target: $ebuTarget"
else
echo "Status of profile \"$SEQ_PROFILE_NAME\" target: $ebuTarget"
fi
}
step_20_alias() { ALIAS='status'; }
step_20() {
shift
local ebuTarget="$EBU_TARGET"
if [ ! -z "$1" ] ; then
ebuTarget="$1"
fi
checkInstalled
exe $toolBin collection-status "$ebuTarget"
}
step_22_info() { echo "List backup files [TARGET]"; }
step_22_alias() { ALIAS='list'; }
step_22() {
shift
local ebuTarget="$EBU_TARGET"
if [ ! -z "$1" ] ; then
ebuTarget="$1"
fi
checkInstalled
exe $toolBin list-current-files "$ebuTarget"
}
step_70_info() {
echo -n "Manage cron file for "
if [ $CONTEXT_HELP -ne 0 ] ; then
echo -n "selected profile"
else
echo -n "profile: $SEQ_PROFILE_NAME"
fi
echo " [OPTIONS]"
echoinfo " [OPTIONS]"
echoinfo " --remove, -r : remove cron file"
}
step_70_alias() { ALIAS='cron'; }
step_70() {
shift
local arg
local cronRemove=0
local cronScript="$toolCronDir/${toolPrefix}$SEQ_PROFILE_NAME"
local cronLog='>/dev/null'
local cronEntry="$EBU_CRONTIME $(whoami) $WDIR/$(basename -- $0) -qq -p $SEQ_PROFILE_NAME"
for arg in "$@" ; do
case "$1" in
--remove|-r)
cronRemove=1
shift
;;
esac
done
if [ ! -z "$EBU_LOG_DIR" ] ; then
cronLog="$EBU_LOG_DIR/${toolPrefix}${SEQ_PROFILE_NAME}.log"
exe touch "$cronLog"
exe chmod 600 "$cronLog"
fi
cronEntry+=" >$cronLog"
if [ -z "$EBU_CRONTIME" ] || [ $cronRemove -ne 0 ] ; then
echo " [I] Removing cron for profile $SEQ_PROFILE_NAME"
exe rm -r "$cronScript"
else
checkFileHead "$cronScript" "$cronEntry"
if [ $? -ne 0 ] ; then
echo " [I] Update cron for profile $SEQ_PROFILE_NAME"
exep "sudo echo \"$cronEntry\" > \"$cronScript\""
syslogEntry "Cron file update complete [$EBU_CRONTIME]"
else
echo " [I] Cron for profile $SEQ_PROFILE_NAME is up to date"
fi
fi
}
step_72_info() { echo "Update all profile cron files"; }
step_72_alias() { ALIAS="reload"; }
step_72() {
for seq in "$SEQ_CONFIG_HOME/"* ; do
seq=$(basename ${seq})
$WDIR/$(basename -- $0) $SEQUENCER_ARGS -qq -p ${seq%%.*} cron
done
}
step_100_info() { echo "Install $toolName $toolPpa"; }
step_100_alias() { ALIAS="install"; }
step_100() {
local aptOpt=
if [ $QUIET -ne 0 ] ; then
aptOpt="-y"
fi
exe add-apt-repository $toolPpa $aptOpt
exe apt install $toolName $aptOpt
}
setPassphrase() {
if [ -z $PASSPHRASE ] && [ ! -z $EBU_PASSPHRASE ] ; then
export PASSPHRASE="$EBU_PASSPHRASE"
fi
}
unsetPassphrase() {
unset PASSPHRASE
}
checkFileHead() {
local readChar
if [ ! -e "$1" ] ; then
echoerr " [E] File $1 not found"
return 1
fi
read -r -n ${#2} readChar < "$1"
if [ "$readChar" == "$2" ] ; then
return 0
fi
return 1
}
syslogEntry() {
if [ "$EBU_SYSLOG" == "true" ] ; then
exe logger -t $toolSyslogTag "$@"
fi
}
checkInstalled() {
if [ -z "$toolBin" ] ; then
command -v $toolName >>/dev/null
if [ $? -ne 0 ] ; then
step install
fi
toolBin="$EBU_PRECMD $(command -v $toolName)"
fi
}
VERSION_SEQREV=12
. /usr/local/bin/sequencer.sh

147
seqs/ejabberd.sh Executable file
View File

@@ -0,0 +1,147 @@
#!/bin/bash
toolName=ejabberd
toolConfLoc="/etc/ejabberd/ejabberd.yml"
toolAdminConf="/etc/ejabberd/ejabberdctl.cfg"
# for http upload
toolStorageLoc="/var/ejabberd"
certRoot="/etc/letsencrypt"
# needed for different steps
myDomain=
myUser=
myPass=
step_1_info() { echo "Install $toolName via apt"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
exe apt install -y $toolName
exe systemctl stop $toolName
}
step_2_info() { echo "Use certificate from local letsencrypt"; }
step_2() {
readDomain
local certLoc="${certRoot}/live/${myDomain}/full.pem"
if [ ! -f "$certLoc" ] ; then
echo "[ERROR] $certLoc not found"
return 1;
fi
local toolCertLoc="/etc/ejabberd/ejabberd.pem"
if [ -f "${toolCertLoc}.bck" ] ; then
echo "[ERROR] Cannot backup original $toolName certificate"
return 1;
fi
exe mv "$toolCertLoc" "${toolCertLoc}.bck"
exe ln -s "$certLoc" "$toolCertLoc"
# read access for ejabberd to read certificate
exe chown root:ejabberd "$certRoot"
exe chmod 750 "$certRoot"
}
step_3_info() { echo "Create basic configuration"; }
step_3() {
if [ ! -f $SEQDIR/ejabberd.yml ] ; then
addConf -m "$MissingConfEntry" "$toolConfLoc"
else
readDomain
echo -e "\nThis user will be the admin:"
readUser
addConf -c "$(cat $SEQDIR/ejabberd.yml)" "$toolConfLoc"
# modify configuration
exe sed -i "s/mydomain\.eu/${myDomain}/" "$toolConfLoc"
exe sed -i "s/myuser/${myUser}/" "$toolConfLoc"
# create storage for http upload
exe mkdir -p "$toolStorageLoc"
exe chown root:$toolName "$toolStorageLoc"
exe chmod 770 "$toolStorageLoc"
fi
# Erlang-VM to listen only on local interface
exe sed -i "s/#\(INET_DIST_INTERFACE=127\.0\.0\.1\)/\1/" "$toolAdminConf"
}
MissingConfEntry="Seq's basic configuration file \"$SEQDIR/ejabberd.yml\" missing.
Backup $toolConfLoc and create a configuration manually.
Some essential settings needed:
- Domain
- Admin User"
step_4_info() { echo "Restart $toolName"; }
step_4_alias() { ALIAS="restart"; }
step_4() {
exe service ejabberd restart
}
step_5_info() { echo "Create new user"; }
step_5_alias() { ALIAS="adduser"; }
step_5() {
readDomain
readUser
readUserPass
exe ejabberdctl register $myUser $myDomain $myPass
}
step_10_info() { echo "List existing user"; }
step_10_alias() { ALIAS="listuser"; }
step_10() {
readDomain
exe ejabberdctl registered_users $myDomain
}
step_12_info() { echo "Change password for existing user"; }
step_12_alias() { ALIAS="passwd"; }
step_12() {
readDomain
readUser
readUserPass
exe ejabberdctl change_password $myUser $myDomain $myPass
}
step_14_info() { echo "Remove registered user"; }
step_14_alias() { ALIAS="deluser"; }
step_14() {
readDomain
readUser
readUserPass
exe ejabberdctl unregister $myUser $myDomain $myPass
}
readDomain() {
if [ "$myDomain" == "" ] ; then
read -p "Enter your domain: " myDomain
endCheckEmpty myDomain "$toolName domain"
fi
}
readUser() {
echo -e "\nDon't use spaces in user name!"
if [ "$myUser" == "" ] ; then
read -p "Enter user name: " myUser
echo
endCheckEmpty myUser "$toolName user name"
fi
}
readUserPass() {
echo -e "\nDon't use spaces in user password!"
if [ "$myPass" == "" ] ; then
read -s -p "Enter user password: " myPass
echo
read -s -p "Enter user password again: " myPass2
echo
if [ "$myPass" != "$myPass2" ] ; then
echo "[ERROR] Passwords don't match"
return 1;
fi
endCheckEmpty myPass "$toolName user password"
fi
}
SEQDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
VERSION_SEQREV=4
. sequencer.sh

321
seqs/ejabberd.yml Normal file
View File

@@ -0,0 +1,321 @@
loglevel: 3
hide_sensitive_log_data: true
log_rotate_size: 0
log_rotate_date: ""
log_rate_limit: 100
hosts:
- "mydomain.eu"
listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
##
## If TLS is compiled in and you installed a SSL
## certificate, specify the full path to the
## file and uncomment these lines:
##
certfile: "/etc/ejabberd/ejabberd.pem"
## starttls: true
##
## To enforce TLS encryption for client connections,
## use this instead of the "starttls" option:
##
starttls_required: true
##
## Custom OpenSSL options
##
protocol_options:
- "no_sslv3"
- "no_tlsv1"
- "no_tlsv1_1"
max_stanza_size: 65536
shaper: c2s_shaper
access: c2s
zlib: true
resend_on_timeout: if_offline
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
-
port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
"/websocket": ejabberd_http_ws
## "/pub/archive": mod_http_fileserver
web_admin: true
http_bind: true
## register: true
## captcha: true
tls: true
certfile: "/etc/ejabberd/ejabberd.pem"
-
port: 5443
module: ejabberd_http
tls: true
certfile: "/etc/ejabberd/ejabberd.pem"
request_handlers:
"upload": mod_http_upload
custom_headers:
"Access-Control-Allow-Origin": "*"
"Access-Control-Allow-Methods": "OPTIONS, HEAD, GET, PUT"
"Access-Control-Allow-Headers": "Authorization"
"Access-Control-Allow-Credentials": "true"
## Disabling digest-md5 SASL authentication. digest-md5 requires plain-text
## password storage (see auth_password_format option).
disable_sasl_mechanisms:
- "digest-md5"
- "x-oauth2"
s2s_use_starttls: required
s2s_certfile: "/etc/ejabberd/ejabberd.pem"
s2s_protocol_options:
- "no_sslv3"
- "no_tlsv1"
- "no_tlsv1_1"
outgoing_s2s_families:
- ipv4
## - ipv6
outgoing_s2s_timeout: 10000
auth_method: internal
auth_password_format: scram
###. ===============
###' DATABASE _SETUP
### MySQL server:
###
#sql_type: mysql
#sql_server: "localhost"
#sql_database: "db_name"
#sql_username: "db_user"
#sql_password: "db_pass"
## Keepalive in seconds
#sql_keepalive_interval: 28800
#sql_pool_size: 5
###. ===============
###' TRAFFIC SHAPERS
shaper:
##
## The "normal" shaper limits traffic speed to 1000 B/s
##
normal: 1000
##
## The "fast" shaper limits traffic speed to 50000 B/s
##
fast: 50000
max_fsm_queue: 1000
###. ====================
###' ACCESS CONTROL LISTS
acl:
admin:
user:
- "myuser": "mydomain.eu"
#- "@localhost"
local:
user_regexp: ""
loopback:
ip:
- "127.0.0.0/8"
shaper_rules:
## Maximum number of simultaneous sessions allowed for a single user:
max_user_sessions: 10
## Maximum number of offline messages that users can have:
max_user_offline_messages:
- 5000: admin
- 100
## For C2S connections, all users except admins use the "normal" shaper
c2s_shaper:
- none: admin
- normal
## All S2S connections use the "fast" shaper
s2s_shaper: fast
###. ============
###' ACCESS RULES
access_rules:
## This rule allows access only for local users:
local:
- allow: local
## Only non-blocked users can use c2s connections:
c2s:
- deny: blocked
- allow
## Only admins can send announcement messages:
announce:
- allow: admin
## Only admins can use the configuration interface:
configure:
- allow: admin
## Only accounts of the local ejabberd server can create rooms:
muc_create:
- allow: local
## Only accounts on the local ejabberd server can create Pubsub nodes:
pubsub_createnode:
- allow: local
## In-band registration allows registration of any possible username.
## To disable in-band registration, replace 'allow' with 'deny'.
register:
- deny
## Only allow to register from localhost
trusted_network:
- allow: loopback
## Do not establish S2S connections with bad servers
s2s:
## - deny:
## - ip: "XXX.XXX.XXX.XXX/32"
## - deny:
## - ip: "XXX.XXX.XXX.XXX/32"
- allow
language: "en"
modules:
mod_adhoc: {}
mod_admin_extra: {}
mod_announce: # recommends mod_adhoc
access: announce
mod_blocking: {} # requires mod_privacy
mod_caps: {}
mod_carboncopy: {}
mod_client_state: {}
mod_configure: {} # requires mod_adhoc
##mod_delegation: {} # for xep0356
mod_disco:
server_info:
-
modules: all
name: "abuse-addresses"
urls:
- "mailto:jabberadmin@mydomain.eu"
mod_echo: {}
mod_irc: {}
mod_http_bind: {}
mod_http_upload:
docroot: "/var/ejabberd"
put_url: "https://@HOST@:5443/upload"
thumbnail: true
dir_mode: "2770"
max_size: 104857600 # 100MB
## mod_http_fileserver:
## docroot: "/var/www"
## accesslog: "/var/log/ejabberd/access.log"
mod_last: {}
mod_muc:
## host: "conference.@HOST@"
access:
- allow
access_admin:
- allow: admin
access_create: muc_create
access_persistent: muc_create
## mod_muc_log: {}
mod_muc_admin: {}
## mod_multicast: {}
mod_offline:
access_max_user_messages: max_user_offline_messages
mod_ping: {}
## mod_pres_counter:
## count: 5
## interval: 60
mod_privacy: {}
mod_private: {}
## mod_proxy65: {}
mod_pubsub:
access_createnode: pubsub_createnode
## reduces resource comsumption, but XEP incompliant
#ignore_pep_from_offline: true
## XEP compliant, but increases resource comsumption
ignore_pep_from_offline: false
last_item_cache: false
max_items_node: 1000
default_node_config:
max_items: 1000
plugins:
- "flat"
- "hometree"
- "pep" # pep requires mod_caps
mod_register:
##
## Protect In-Band account registrations with CAPTCHA.
##
## captcha_protected: true
##
## Set the minimum informational entropy for passwords.
##
## password_strength: 32
##
## After successful registration, the user receives
## a message with this subject and body.
##
## welcome_message:
## subject: "Welcome!"
## body: |-
## Hi.
## Welcome to this XMPP server.
##
## When a user registers, send a notification to
## these XMPP accounts.
##
## registration_watchers:
## - "admin1@example.org"
##
## Only clients in the server machine can register accounts
##
## ip_access: trusted_network
##
## Local c2s or remote s2s users cannot register accounts
##
## access_from: deny
## access: register
# No registration, but allow existing accounts to change password
access: none
mod_roster:
versioning: true
mod_shared_roster: {}
mod_stats: {}
mod_time: {}
mod_vcard:
search: false
mod_version:
show_os: false
##
## Enable modules with custom options in a specific virtual host
##
## host_config:
## "localhost":
## modules:
## mod_echo:
## host: "mirror.localhost"
##
## Enable modules management via ejabberdctl for installation and
## uninstallation of public/private contributed modules
## (enabled by default)
##
allow_contrib_modules: true
###.
###'
### Local Variables:
### mode: yaml
### End:
### vim: set filetype=yaml tabstop=8 foldmarker=###',###. foldmethod=marker:

View File

@@ -0,0 +1,6 @@
#!/bin/bash
# Matrix element web sequence configuration
ELEMENT_WEB_LOC="/var/www/element"
ELEMENT_WEB_BACKUP="/root/backup/element"

164
seqs/element-web.sh Executable file
View File

@@ -0,0 +1,164 @@
#!/bin/bash
toolName=element-web
latestUrl="https://api.github.com/repos/vector-im/element-web/releases/latest"
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="${toolName}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
echo " ${toolName} path: ${ELEMENT_WEB_LOC}"
echo " ${toolName} backup: ${ELEMENT_WEB_BACKUP}"
CONFIG=1
fi
}
step_18_info() { echo "Check for updates"; }
step_18_alias() { ALIAS="updatecheck"; }
step_18() {
shift
local latestVersion=
if [ ! -z $1 ] ; then
latestVersion="$1"
else
latestVersion=$(curl --silent "$latestUrl" | grep -Po '"tag_name": "v\K.*?(?=")')
fi
local isInstalled=$(grep -E "${latestVersion}" "${ELEMENT_WEB_LOC}/version" >>/dev/null && echo "1" || echo "0")
if [ $isInstalled -eq 1 ] ; then
echo " [I] Version $latestVersion is already installed"
return 1
else
echo " [I] Update to $latestVersion available"
fi
return 0
}
step_20_info() {
echo -n "Create a backup [ELEMENT WEB ROOT]"
if [ $CONFIG -ne 0 ] ; then
echo " at $ELEMENT_WEB_BACKUP"
else
echo
fi
}
step_20_alias() { ALIAS="backup"; }
step_20() {
shift
local tempRoot=
if [ $CONFIG -eq 0 ] ; then
echoerr " [E] No configuration file found"
return 1
fi
if [ ! -z $ELEMENT_WEB_BACKUP ] ; then
exe mkdir -p "$ELEMENT_WEB_BACKUP"
fi
if [ ! -z $1 ] ; then
tempRoot="$1"
else
tempRoot="$ELEMENT_WEB_LOC"
fi
local wwwBackup="$ELEMENT_WEB_BACKUP/${toolName}_www_`date +%Y%m%d-%H%M%S`.tar.gz"
echo " [I] Backing up webserver directory to $wwwBackup"
exe cd "$tempRoot/.."
exe tar czf "$wwwBackup" $(basename "$tempRoot")
}
step_22_info() {
shift
if [ -z $1 ] ; then
echo -n "Get latest version from github"
if [ $CONTEXT_HELP -eq 0 ] ; then
echo ": $(curl --silent "$latestUrl" | grep -Po '"tag_name": "\K.*?(?=")')"
else
echo " [CUSTOM VERSION]"
fi
else
echo "Get version $1 from github"
fi
}
step_22_alias() { ALIAS="upgrade"; }
step_22() {
shift # don't need step number
local latestVersion=
if [ ! -z $1 ] ; then
latestVersion="$1"
else
latestVersion=$(curl --silent "$latestUrl" | grep -Po '"tag_name": "v\K.*?(?=")')
fi
if [ -z $latestVersion ] ; then
echoerr " [E] Cannot determine latest version from github repository"
return 1
elif [ $QUIET -eq 0 ] ; then
echo
exe read -p "Install $latestVersion to $ELEMENT_WEB_LOC [n]o/(y)es? " answer
case $answer in
[yY])
;;
*)
echoerr " [I] Upgrade aborted"
return 1
;;
esac
fi
local isInstalled=$(grep -E "${latestVersion}" "${ELEMENT_WEB_LOC}/version" >>/dev/null && echo "1" || echo "0")
if [ $isInstalled -eq 1 ] ; then
echo " [I] Version $latestVersion is already installed"
return 0
fi
# Download
local downUrl="https://github.com/vector-im/element-web/releases/download/v${latestVersion}/element-v${latestVersion}.tar.gz"
local tempExtract="$tempDown/element-v$latestVersion"
if [ ! -e "$tempExtract" ] ; then
exe mkdir -p "$tempDown"
exe wget -O "$tempLoc" $downUrl
endReturn -o $? "Download failed: $downUrl"
exe cd "$tempDown"
exe tar -xf "$tempLoc"
endReturn -o $? "Extract failed: $tempLoc"
else
echo " [I] Found existing download: $tempExtract"
fi
# Installation
local tempBu="${ELEMENT_WEB_LOC}_bu_`date +%Y%m%d-%H%M%S`"
exe mv "$ELEMENT_WEB_LOC" "$tempBu"
step backup "$tempBu"
endReturn -o $? "Backup failed; $ELEMENT_WEB_LOC renamed!"
echo " [I] Installing version $latestVersion to $ELEMENT_WEB_LOC"
exe mv "$tempExtract" "$ELEMENT_WEB_LOC"
exe chown -R www-data: "$ELEMENT_WEB_LOC"
# Configuration
echo " [I] Copying configuration"
exe cp -ar "$tempBu/config.json" "$ELEMENT_WEB_LOC/"
echo " [I] Copying login background"
exe cp -ar "$tempBu/$tempBackImg/"* "$ELEMENT_WEB_LOC/$tempBackImg/"
exe rm -rf "$tempBu"
}
tempBackImg="themes/element/img/backgrounds"
tempDown="/tmp/${toolName}"
tempLoc="$tempDown/${toolName}.tar.gz"
step_24_info() { echo "Clean temporary files: $tempDown"; }
step_24_alias() { ALIAS="clean"; }
step_24() {
exe rm -rf "$tempDown"
}
VERSION_SEQREV=11
. /usr/local/bin/sequencer.sh

89
seqs/fail2ban.sh Executable file
View File

@@ -0,0 +1,89 @@
#!/bin/bash
toolName=fail2ban
toolDeps="$toolName"
toolConfDir="/etc/fail2ban"
toolConfLoc="$toolConfDir/jail.local"
toolFilter="$toolConfDir/filter.d"
toolJails="$toolConfDir/jail.d"
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="${toolName}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
CONFIG_DIR="$WDIR/fail2ban"
CONFIG_FILTER="$CONFIG_DIR/filter.d"
CONFIG_JAILS="$CONFIG_DIR/jail.d"
#step_config() {
# echo "Called once before executing steps."
# ## e.g. to source a config file manually:
# #. "$CONFIG_FILE"
# ## or to use sequencer api:
# #initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
# #if [ $? -eq 0 ] ; then
# # CONFIG=1
# #fi
#}
step_1_info() { echo "Install $toolName"; }
step_1_alias() { ALIAS="install"; }
step_1() {
local aptOpt=
if [ $QUIET -ne 0 ];then
aptOpt="-y"
fi
exe apt update
exe apt install $toolDeps $aptOpt
}
step_2_info() { echo "Base jail configuration to use ufw"; }
step_2_alias() { ALIAS="config"; }
step_2() {
echo " [I] Create local configuration";
addConf -f "$failConfLocal" "$toolConfLoc"
exe service $toolName restart
}
failConfLocal="[DEFAULT]
banaction = ufw
banaction_multiport = ufw
ignoreip = 127.0.0.1/8 ::1"
step_3_info() { echo "Add basic ip-blacklist"; }
step_3_alias() { ALIAS="blacklist"; }
step_3() {
echo " [I] Adding filter"
addConf -s -f "$ipBlackListFilter" "$toolFilter/$(basename $ipBlackListFilter)"
addConf -s -f "$ipBlackListJail" "$toolJails/$(basename $ipBlackListJail)"
addConf -s -f "$ipBlackList" "$toolConfDir/$(basename $ipBlackList)"
exe service $toolName restart
}
ipBlackList="$CONFIG_DIR/ip.blacklist"
ipBlackListJail="$CONFIG_JAILS/ip-blacklist.conf"
ipBlackListFilter="$CONFIG_FILTER/ip-blacklist.conf"
step_4_info() { echo "$toolName notes"; }
step_4_alias() { ALIAS="notes"; }
step_4() {
cat <<NOTES_EOF
# Syslog not readable by librenms (https://github.com/fail2ban/fail2ban/issues/2734)
[$toolConfDir/fail2ban.local]
[Definition]
logtarget = SYSLOG[format="%%(name)s[%%(process)d]: %%(levelname)s %%(message)s"]
NOTES_EOF
}
step_20_info() { echo "Install mailserver jail"; }
step_20_alias() { ALIAS="mail"; }
step_20() {
addConf -s -f "$mailJail" "$toolJails/$(basename $mailJail)"
exe service $toolName restart
}
mailJail="$CONFIG_JAILS/mail.conf"
VERSION_SEQREV=11
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,8 @@
[Definition]
datepattern = %%Y/%%m/%%d %%H:%%M(?::%%S)?
failregex = ^<HOST> \[.*\]$
ignoreregex =

View File

@@ -0,0 +1,4 @@
[Definition]
failregex = ^.*\"remoteAddr\":\"<HOST>\".*Trusted domain error.*$
^.*\"remoteAddr\":\"<HOST>\".*Login failed:.*$

View File

@@ -0,0 +1,2 @@
#37.49.224.142 [2021/05/23 09:00]
#37.49.224.142 [2021/05/23 16:00:00]

View File

@@ -0,0 +1,16 @@
[ip-blacklist]
enabled = true
port = anyport
filter = ip-blacklist
logpath = /etc/fail2ban/ip.blacklist
maxretry = 0
findtime = 600
# infinite ban
#bantime = -1
# 1 day ban
#bantime = 24h
# 2 day ban
bantime = 48h
# 10 minute ban
#bantime = 10m

View File

@@ -0,0 +1,21 @@
[dovecot]
enabled = true
port = smtp,ssmtp,pop3,pop3s,imap,imap2,imaps
filter = dovecot
logpath = /var/log/mail.log
maxretry = 3
bantime = 24h
[postfix]
enabled = true
port = smtp,ssmtp
filter = postfix
logpath = /var/log/mail.log
maxretry = 3
[postfix-sasl]
enabled = true
port = smtp,ssmtp,imap2,imaps,pop3,pop3s
filter = postfix[mode=auth]
logpath = /var/log/mail.log
maxretry = 3

View File

@@ -0,0 +1,7 @@
[nextcloud]
enabled = true
logpath = /var/nc_data/nextcloud.log
port = http,https
filter = nextcloud
maxretry = 3
bantime = 24h

154
seqs/fhem.sh Executable file
View File

@@ -0,0 +1,154 @@
#!/bin/bash
toolName="fhem"
toolUser="$toolName"
toolHome="/opt/fhem"
toolVersion="6.0"
toolDpkg="fhem-${toolVersion}.deb"
toolUrl="http://fhem.de/$toolDpkg"
# default deps listed at https://debian.fhem.de/
toolDeps="perl-base libdevice-serialport-perl libwww-perl libio-socket-ssl-perl libcgi-pm-perl libjson-perl sqlite3 libdbd-sqlite3-perl libtext-diff-perl libtimedate-perl libmail-imapclient-perl libgd-graph-perl libtext-csv-perl libxml-simple-perl liblist-moreutils-perl fonts-liberation2 libimage-librsvg-perl libgd-text-perl libsocket6-perl libio-socket-inet6-perl libmime-base64-urlsafe-perl libimage-info-perl libusb-1.0-0-dev libnet-server-perl"
toolDeps2="libdate-manip-perl libhtml-treebuilder-xpath-perl libmojolicious-perl libxml-bare-perl libauthen-oath-perl libconvert-base32-perl libmodule-pluggable-perl libnet-bonjour-perl libcrypt-urandom-perl"
# for rounding operations e.g.:
# { use Math::Round qw/nearest/;; nearest('0.01',ReadingsVal("1WT_28_5728E9070000", "temperature", 0)-1.1);; }
toolDeps2+=" libmath-round-perl"
# for fritzbox connection
toolDeps2+=" libsoap-lite-perl libjson-xs-perl"
# for xmpp support (no special solution needed for raspbian buster)
toolDeps2+=" libnet-xmpp-perl libxml-stream-perl libnet-jabber-perl"
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
WSUBDIR="${WDIR}/${toolName}"
#CONFIG_FILE="$WDIR/${toolName}.cfg"
#CONFIG_FILE_DEFAULT="${CONFIG_FILE}.example"
#step_config() {
# echo "Called once before executing steps."
# echo "e.g. to source a config file:"
# #. "$CONFIG_FILE"
#}
step_1_info() { echo "Install prerequisits for $toolName"; }
step_1_alias() { ALIAS="install"; }
step_1() {
local aptOpt=
if [ $QUIET != 0 ] ; then
aptOpt="-y"
fi
#exe apt update
exe apt install $toolDeps $toolDeps2 "$aptOpt"
#exe apt install "$toolDeps2" "$aptOpt"
endReturn -o $? "Installation of prerequisits failed"
}
step_2_info() { echo "Download and install $toolName version $toolVersion"; }
step_2() {
exe wget "$toolUrl" -O "$downPath"
endReturn -o $? "Download of $toolName failed"
exe dpkg -i "$downPath"
endReturn -o $? "Installation of $toolName failed"
}
downPath="/tmp/$toolDpkg"
step_3_info() { echo "Start $toolName service"; }
step_3() {
exe systemctl restart fhem.service
}
step_20_info() { echo "List $toolName prerequisits"; }
step_20_alias() { ALIAS="listdeps"; }
step_20() {
echo " [I] $toolName prerequisits:"
echo "$toolDeps $toolDeps2"
}
step_30_info() { echo "Create user $toolUser"; }
step_30() {
exe useradd --system --home "$toolHome" --gid dialout --shell /bin/false "$toolUser"
endReturn -o $? "Creating user $toolUser failed"
}
step_32_info() { echo "Create $toolName systemd service"; }
step_32() {
exe cp "${toolHome}/contrib/init-scripts/fhem.service" "$systemdConfigLoc"
exe systemctl daemon-reload
}
systemdConfigLoc="/etc/systemd/system"
step_34_info() { echo "Downgrade $toolName jabber dependencies (callbackIQ -> FHEM crash)"; }
step_34_alias() { ALIAS="downgrade_xmpp"; }
step_34() {
if [ ! -f $libnetDown ]; then
exe wget "$libnetUrl" -O "$libnetDown"
endReturn -o $? "Download of $libnetUrl failed"
fi
if [ ! -f $libxmlDown ]; then
exe wget "$libxmlUrl" -O "$libxmlDown"
endReturn -o $? "Download of $libxmlUrl failed"
fi
local aptOption=
if [ $QUIET -ne 0 ] ; then
aptOption="-y"
else
aptOption=""
fi
exe apt remove libnet-jabber-perl $aptOption
saveReturn $?
exe apt remove libnet-xmpp-perl $aptOption
saveReturn $?
exe apt remove libxml-stream-perl $aptOption
saveReturn $?
endReturn "Failed removing packages; Manual fix required"
exe dpkg -i "$libxmlDown"
saveReturn $?
exe dpkg -i "$libnetDown"
saveReturn $?
exe apt install libnet-jabber-perl $aptOption
saveReturn $?
endReturn "Failed removing packages; Manual fix required"
exe rm "$libxmlDown" "$libnetDown"
}
libnetName="libnet-xmpp-perl_1.02-3_all.deb"
libnetDown="/tmp/$libnetName"
libnetUrl="http://ftp.de.debian.org/debian-archive/debian/pool/main/libn/libnet-xmpp-perl/$libnetName"
libxmlName="libxml-stream-perl_1.23-2_all.deb"
libxmlDown="/tmp/$libxmlName"
libxmlUrl="http://ftp.de.debian.org/debian/pool/main/libx/libxml-stream-perl/$libxmlName"
step_35_info() { echo "Pin downgraded $toolName jabber dependencies"; }
step_35() {
addConf -s "$aptPinXmpp" "$aptPinFile"
}
aptPinFile="/etc/apt/preferences.d/00_FhemJabber"
aptPinXmpp="Package: libnet-xmpp-perl
Pin: version 1.02-3*
Pin-Priority: 1000
Package: libxml-stream-perl
Pin: version 1.23-2
Pin-Priority: 1000"
step_37_info() { echo "Download latest speedtest python script"; }
step_37_alias() { ALIAS="speedtestdownload"; }
step_37() {
local lSpeedPath="/usr/local/bin/speedtest-cli"
exe wget -O "$lSpeedPath" https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py
exe chmod +x "$lSpeedPath"
}
step_40_info() { echo "Execute fhem [COMMAND]"; }
step_40_alias() { ALIAS="exe"; }
step_40() {
shift
exe perl "${toolHome}/fhem.pl" 7072 "$1"
}
VERSION_SEQREV=11
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,7 @@
# Datei: /etc/udev/rules.d/20-FehmIf.rules
# Gerät CUL868 busware.de (homematic RF) an USB
SUBSYSTEM=="tty", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204b", SYMLINK+="tty_CUL868"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0200", SYMLINK+="tty_Zwave"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A40352S9", SYMLINK+="ttyUSB_RS485"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A103R0XO", SYMLINK+="ttyUSB_LinkUSBi"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="FT8YS9UP", SYMLINK+="ttyUSB_Comfoair"

View File

@@ -0,0 +1,9 @@
#!/bin/bash
## Freeradius settings
FRAD_DB_NAME="radius"
FRAD_DB_USER="radius"
# Default freeradius database password: radpass
## Daloradius settings
DRAD_HOME="/var/www/daloradius"

73
seqs/freeradius.sh Executable file
View File

@@ -0,0 +1,73 @@
#!/bin/bash
toolName=freeradius
toolConfLoc="/etc/freeradius/3.0"
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
## or to use sequencer api with profile config file support:
initSeqConfig "$SCRIPT_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
echoseq " [I] Freeradius DB: $FRAD_DB_NAME"
echoseq " Daloradius home: $DRAD_HOME"
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return -1
fi
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && APTOPT="-y"
## Return of non zero value will abort the sequence
return 0
}
step_50_info() { echo "Init freeradius and daloradius database"; }
step_50_alias() { ALIAS="initdb"; }
step_50() {
local drDbInit="$DRAD_HOME/contrib/db/mysql-daloradius.sql"
local frDbSchema="$toolConfLoc/mods-config/sql/main/mysql/schema.sql"
local frDbSetup="$toolConfLoc/mods-config/sql/main/mysql/setup.sql"
exe "$WDIR"/mysql.sh createdb -c utf8 -d "$FRAD_DB_NAME" -u "$FRAD_DB_USER"
endReturn -o $? "Creating database failed"
exep "mysql -uroot \"$FRAD_DB_NAME\" < $frDbSchema"
#exep "mysql -uroot \"$FRAD_DB_NAME\" < $frDbSetup"
exep "mysql -uroot \"$FRAD_DB_NAME\" < $drDbInit"
}
step_52_info() { echo "Reset freeradius and daloradius database"; }
step_52_alias() { ALIAS="resetdb"; }
step_52() {
local lAnswer
if [ $QUIET -eq 0 ]; then
read -p "Do you really want to reset the database $FRAD_DB_NAME y/[n]? " lAnswer
else
lAnswer=y
fi
case "$lAnswer" in
[yY])
echoseq -n " [I] Reseting DB...";;
*)
echoerr " [I] Abort reset"
return 1;;
esac
exe mysql -e "DROP DATABASE $FRAD_DB_NAME"
step initdb
}
VERSION_SEQREV=13
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,9 @@
#!/bin/bash
# Friendica sequence configuration
# FR = Friendica
FR_LOC="/var/www/friendica"
FR_LOC_DATA="/var/fd_data"
FR_BACKUP="/root/backup/friendica"
FR_DATABASE="friendica_db"

172
seqs/friendica.sh Executable file
View File

@@ -0,0 +1,172 @@
#!/bin/bash
toolName=friendica
latestUrl="https://api.github.com/repos/friendica/friendica/releases/latest"
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="${toolName}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
fi
}
step_20_info() {
shift
echoinfoArgs "[FRIENDICA ROOT]"
echo -n "Create a backup"
if [ $CONFIG -ne 0 ] ; then
echo " at $FR_BACKUP"
else
echo
fi
}
step_20_alias() { ALIAS="backup"; }
step_20() {
shift
local tempRoot=
if [ $CONFIG -eq 0 ] ; then
echoerr " [E] No configuration file found"
return 1
fi
if [ ! -z $FR_BACKUP ] ; then
exe mkdir -p "$FR_BACKUP"
fi
if [ ! -z "$1" ] ; then
tempRoot="$1"
else
tempRoot="$FR_LOC"
fi
exe $WDIR/mysql.sh -qq backup "$FR_DATABASE" "$FR_BACKUP"
endReturn -o $? "Backup mysql database failed"
[ ! -e "$tempRoot" ] && endReturn -o 1 -f "Friendica root $tempRoot not found"
local wwwBackup="$FR_BACKUP/${toolName}_www_`date +%Y%m%d-%H%M%S`.tar.gz"
local dataBackup="$FR_BACKUP/${toolName}_data_`date +%Y%m%d-%H%M%S`.tar.gz"
echo " [I] Backing up webserver directory to $wwwBackup"
exe cd "$tempRoot/.."
exe tar czf "$wwwBackup" $(basename "$tempRoot")
echo " [I] Backing up data directory to $dataBackup"
exe cd "$FR_LOC_DATA/.."
exe tar czf "$dataBackup" $(basename "$FR_LOC_DATA")
}
step_22_info() {
shift
if [ -z $1 ] ; then
echo -n "Get latest version from github"
if [ $CONTEXT_HELP -eq 0 ] ; then
echo ": $(curl --silent "$latestUrl" | grep -Po '"tag_name": "\K.*?(?=")')"
else
echo " [CUSTOM VERSION]"
fi
else
echo "Get version $1 from github"
fi
}
step_22_alias() { ALIAS="upgrade"; }
step_22() {
shift # don't need step number
local latestVersion=
if [ ! -z $1 ] ; then
latestVersion="$1"
else
latestVersion=$(curl --silent "$latestUrl" | grep -Po '"tag_name": "\K.*?(?=")')
fi
if [ -z $latestVersion ] ; then
echoerr " [E] Cannot determine latest version from github repository"
return 1
elif [ $QUIET -eq 0 ] ; then
echo
exe read -p "Install $latestVersion to $FR_LOC [n]o/(y)es? " answer
case $answer in
[yY])
;;
*)
echoerr " [I] Upgrade aborted"
return 1
;;
esac
fi
local isInstalled=$(grep -E "Version $latestVersion" "${FR_LOC}/CHANGELOG" >>/dev/null && echo "1" || echo "0")
if [ $isInstalled -eq 1 ] ; then
echoerr " [E] Version $latestVersion is already installed"
return 2
fi
# Download
local downUrl="https://files.friendi.ca/friendica-full-${latestVersion}.tar.gz"
local downUrlAddons="https://files.friendi.ca/friendica-addons-${latestVersion}.tar.gz"
local tempExtract="$tempDown/friendica-full-$latestVersion"
local tempExtractAddons="$tempDown/friendica-addons-$latestVersion"
if [ ! -e "$tempExtract" ] ; then
exe mkdir -p "$tempDown"
exe wget -O "$tempLoc" $downUrl
endReturn -o $? "Download failed: $downUrl"
exe cd "$tempDown"
exe tar -xf "$tempLoc"
endReturn -o $? "Extract failed: $tempLoc"
else
echo " [I] Found existing download: $tempExtract"
fi
if [ ! -e "$tempExtractAddons" ] ; then
exe wget -O "$tempLocAddons" $downUrlAddons
endReturn -o $? "Download failed: $downUrlAddons"
exe cd "$tempDown"
exe mkdir -p "$tempExtractAddons"
exe tar -xC "${tempExtractAddons}" -f "$tempLocAddons"
endReturn -o $? "Extract failed: $tempLocAddons"
else
echo " [I] Found existing download: $tempExtractAddons"
fi
# Installation
local tempBu="${FR_LOC}_bu_`date +%Y%m%d-%H%M%S`"
local tempAddons="${FR_LOC}/addon"
exe mv "$FR_LOC" "$tempBu"
step backup "$tempBu"
endReturn -o $? "Backup failed; $FR_LOC renamed!"
echo " [I] Installing version $latestVersion to $FR_LOC"
exe mv "$tempExtract" "$FR_LOC"
exe mv "$tempExtractAddons" "$tempAddons"
exe chown -R www-data: "$FR_LOC"
# Configuration
echo " [I] Copying configuration"
exe cp -ar "$tempBu/config/local.config.php" "$FR_LOC/config/"
if [ -f "$tempBu/config/addon.config.php" ]; then
exe cp -ar "$tempBu/config/addon.config.php" "$FR_LOC/config/"
fi
# Custom landing page
if [ -f "$tempBu/home.html" ]; then
exe cp -ar "$tempBu/home".* "$FR_LOC/"
fi
echo " [I] Don't forget to \"clean\" if everything is working as expected"
}
tempDown="/tmp/friendica"
tempLoc="$tempDown/fr.tar.gz"
tempLocAddons="$tempDown/fradd.tar.gz"
step_24_info() { echo "Clean temporary files: $tempDown"; }
step_24_alias() { ALIAS="clean"; }
step_24() {
exe rm -rf "$tempDown"
}
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

52
seqs/git.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/bin/bash
toolName=git
# Get script working directory
# (when called from a different directory and even when called via symlink)
WDIR="$(cd "$(dirname -- "$(realpath ${BASH_SOURCE[0]})")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
## or to use sequencer api with global config file:
#initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
#if [ $? -eq 0 ] ; then
# CONFIG=1
#else
# # End if no configuration file exists
# [ $DRY -eq 0 ] && return -1
#fi
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && APTOPT="-y"
## Return of non zero value will abort the sequence
return 0
}
step_1_info() { echo "Setup global git aliases"; }
step_1_alias() { ALIAS="alias"; }
step_1() {
local brConf="branch \
--format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - \
%(contents:subject) %(color:green)(%(committerdate:relative)) [%(authorname)]' \
--sort=-committerdate"
local logConf="!git log --pretty=format:\"%C(magenta)%h%Creset \
-%C(red)%d%Creset %s %C(dim green)(%cr) [%an]\" --abbrev-commit -30"
exe git config --global alias.s 'status -s'
exe git config --global alias.st 'status'
exe git config --global alias.co 'checkout'
exe git config --global alias.ci 'commit'
exe git config --global alias.b "${brConf}"
exe git config --global alias.br 'branch'
exe git config --global alias.l "${logConf}"
exe git config --global alias.ll 'log'
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh

57
seqs/gitea.cfg.example Normal file
View File

@@ -0,0 +1,57 @@
#!/bin/bash
SEQ_GITEA_USER="git"
SEQ_GITEA_BIN_LOC="/usr/local/bin/gitea"
SEQ_GITEA_BASE_DIR="/var/lib/gitea"
SEQ_GITEA_WORK_DIR="$SEQ_GITEA_BASE_DIR/work"
SEQ_GITEA_HOME_DIR="$SEQ_GITEA_BASE_DIR/home"
SEQ_GITEA_CONF_DIR="$SEQ_GITEA_BASE_DIR/config"
SEQ_GITEA_BACKUP_DIR="$SEQ_GITEA_BASE_DIR/backup"
# Service Derived from
# https://raw.githubusercontent.com/go-gitea/gitea/master/contrib/systemd/gitea.service
SEQ_GITEA_SERVICE="[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
Requires=mysql.service
[Service]
# Modify these two values and uncomment them if you have
# repos with lots of files and get an HTTP error 500 because
# of that
###
#LimitMEMLOCK=infinity
#LimitNOFILE=65535
RestartSec=2s
Type=simple
User=$SEQ_GITEA_USER
Group=$SEQ_GITEA_USER
WorkingDirectory=$SEQ_GITEA_WORK_DIR
# If using Unix socket: tells systemd to create the /run/gitea folder, which will contain the gitea.sock f
# (manually creating /run/gitea doesn't work, because it would not persist across reboots)
#RuntimeDirectory=gitea
ExecStart=/usr/local/bin/gitea web --config \"$SEQ_GITEA_CONF_DIR/app.ini\"
Restart=always
Environment=USER=\"$SEQ_GITEA_USER\" HOME=\"$SEQ_GITEA_HOME_DIR\" GITEA_WORK_DIR=\"$SEQ_GITEA_WORK_DIR\"
# If you install Git to directory prefix other than default PATH (which happens
# for example if you install other versions of Git side-to-side with
# distribution version), uncomment below line and add that prefix to PATH
# Don't forget to place git-lfs binary on the PATH below if you want to enable
# Git LFS support
#Environment=PATH=/path/to/git/bin:/bin:/sbin:/usr/bin:/usr/sbin
# If you want to bind Gitea to a port below 1024, uncomment
# the two values below, or use socket activation to pass Gitea its ports as above
###
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
#AmbientCapabilities=CAP_NET_BIND_SERVICE
###
[Install]
WantedBy=multi-user.target"

View File

@@ -4,119 +4,205 @@
## Installation of self hosted git service Gitea
toolName="gitea"
giteaDownload="https://dl.gitea.io/gitea/1.7.5/gitea-1.7.5-linux-arm-7"
giteaService="https://raw.githubusercontent.com/go-gitea/gitea/master/contrib/systemd/gitea.service"
giteaServiceLoc="/etc/systemd/system/gitea.service"
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_1_info() { echo "Updating apt"; }
step_1() {
apt update
giteaLatestUrl="https://api.github.com/repos/go-gitea/gitea/releases/latest"
giteaVersion=$(curl --silent "$giteaLatestUrl" | grep -Po '"tag_name": "v\K.*?(?=")')
giteaArch=
giteaDownloadEval='https://dl.gitea.io/gitea/${giteaVersion}/gitea-${giteaVersion}-linux-${giteaArch}'
giteaDownload=$(eval echo $giteaDownloadEval)
giteaDir="/usr/local/bin"
giteaServiceLoc="/etc/systemd/system/gitea.service"
giteaLogDir="/var/log/gitea"
giteaIniLoc=
giteaDownFile="/tmp/giteaDown"
giteaUser="git"
versionNow=
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return -1
fi
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && APTOPT="-y"
if [ -z $giteaVersion ] ; then
echoerr " [E] Couldn't determine latest version of $toolName"
fi
[ ! -z "$(command -v gitea)" ] && versionNow=$(gitea --version | sed 's/.*version \([0-9.]\+\).*/\1/')
checkArchitecture
giteaIniLoc="${SEQ_GITEA_CONF_DIR}/app.ini"
echoseq " [I] Gitea work: $SEQ_GITEA_WORK_DIR"
echoseq " Gitea config: $SEQ_GITEA_CONF_DIR"
echoseq " Git user home: $SEQ_GITEA_HOME_DIR"
echoseq
outColor yellow
echoseq " [W] Don't forget to adapt $SEQ_GITEA_CONF_DIR/app.ini"
outColor
## Return of non zero value will abort the sequence
return 0
}
step_2_info() { echo "Downloading $toolName to user home: $giteaDownload"; }
checkArchitecture() {
[ ! -z "$(command -v dpkg)" ] && giteaArch=$(dpkg --print-architecture)
case $giteaArch in
armhf)
giteaArch="arm-6";;
esac
giteaDownload=$(eval echo $giteaDownloadEval)
}
step_1_info() { echo "Updating apt"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
}
step_2_info() {
[ -z "$giteaArch" ] && checkArchitecture
echo "Downloading $toolName to user home from:"
echoinfo "$giteaDownload"
}
step_2() {
cd
wget -O gitea $giteaDownload
exe wget -O "$giteaDownFile" $giteaDownload
saveReturn $?
endReturn
}
step_3_info() { echo "Adding user for $toolName (git:git)"; }
step_3_info() { echo "Adding user for $toolName ($giteaUser)"; }
step_3() {
adduser \
--system \
--shell /bin/bash \
--gecos 'Git Version Control' \
--group \
--disabled-password \
--home /home/git \
git
exe adduser \
--system \
--shell /bin/bash \
--gecos 'Git Version Control' \
--group \
--disabled-password \
--home "$SEQ_GITEA_HOME_DIR" \
"$SEQ_GITEA_USER"
saveReturn $?
endReturn
}
step_4_info() { echo "Create required directory structure"; }
step_4() {
mkdir -p /var/lib/gitea/{custom,data,log}
chown -R git: /var/lib/gitea/
chmod -R 750 /var/lib/gitea/
mkdir /etc/gitea
chown root:git /etc/gitea
chmod 770 /etc/gitea
echo "Copying gitea to global location and making it executable"
chmod +x ~/gitea
cp ~/gitea /usr/local/bin/gitea
saveReturn $?
endReturn
exe install -o $SEQ_GITEA_USER -g $SEQ_GITEA_USER -m 750 \
-d "$SEQ_GITEA_BACKUP_DIR" "$SEQ_GITEA_CONF_DIR" \
"$SEQ_GITEA_HOME_DIR" "$SEQ_GITEA_WORK_DIR"/{custom,data,log}
exe chown root:$SEQ_GITEA_USER "$SEQ_GITEA_CONF_DIR"
exe chmod 770 $SEQ_GITEA_CONF_DIR
echoseq "Creating $giteaLogDir"
exe install -g $SEQ_GITEA_USER -m 770 -d "$giteaLogDir"
echoseq -n "Copying gitea to global location and making it executable..."
exe install -b -m 755 -T "$giteaDownFile" "$SEQ_GITEA_BIN_LOC" && echo "ok"
endReturn "Failed to install $SEQ_GITEA_BIN_LOC"
}
step_5_info() { echo "Creating systemd service"; }
step_5() {
wget -O $giteaServiceLoc $giteaService
echo -en "Uncomment needed services mysql (enter to continue): "
read
vi $giteaServiceLoc
addConf -c "$SEQ_GITEA_SERVICE" "$giteaServiceLoc"
}
step_6_info() { echo -e "Starting $toolName service\n"; }
step_6_info() { echo "Starting $toolName service"; }
step_6() {
systemctl enable gitea
systemctl start gitea
echo "Before proceeding to installation you may need to create a database first with step 10"
echo
echo "Goto http://[yourip]:3000/install and complete installation"
echo
echo "Afterwards please execute step 20 to secure configuration"
exe systemctl enable gitea --now
echoseq "Before proceeding to installation you may need to create a database first with step 10"
echoseq
echoseq "Goto http://[yourip]:3000/install and complete installation"
echoseq
echoseq "Afterwards please execute step 20 to secure configuration"
}
step_7_info() { echo "Show configuration notes"; }
step_7_alias() { ALIAS="notes"; }
step_7() {
outColor green
cat <<NOTES_END
Final configuration notes for $giteaIniLoc:
step_10_info() { echo -e "Create mysql database for $toolName\n"; }
[repository]
DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = true
[server]
# Don't show home page
LANDING_PAGE = explore
[mailer]
# Allow local MTA without valid certificate
SKIP_VERIFY = true
[service]
# Use correct user identity when changing files in the web frontend
NO_REPLY_ADDRESS = yourdomain.com
[attachment]
# Allow more archives to be uploaded
ALLOWED_TYPES=application/zip|application/gzip|application/x-zip|application/x-gzip|application/x-shellscript|text/markdown
NOTES_END
}
step_10_info() { echo "Create mysql database for $toolName"; }
step_10() {
local mysqlDatabase
local mysqlUser
local mysqlPass
exe "$WDIR/mysql.sh" -qq createdb --charset utf8mb4
}
echo "Existing mysql databases:"
mysql -u root -e 'SHOW DATABASES;'
step_12_info() {
if [ ! -z "$versionNow" ] ; then
if [ "$giteaVersion" == "$versionNow" ] ; then
echo "No upgrade available. Already on latest: $versionNow"
else
echo "Download new version $giteaVersion to /usr/local/bin"
echoinfo " - installed version: $versionNow -"
fi
else
echo "Upgrade existing $toolName installation"
fi
}
step_12_alias() { ALIAS="upgrade"; }
step_12() {
endCheckEmpty versionNow "Please install $toolName first"
exe wget -O "$giteaDownFile" $giteaDownload
endReturn -o $? "Download failed"
echo -en "Enter database name: "
read mysqlDatabase
endCheckEmpty mysqlDatabase "database name"
mysql -u root -e 'CREATE DATABASE '$mysqlDatabase' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'
saveReturn $?
endReturn
echo "Existing mysql user:"
mysql -u root -e 'SELECT User, Host FROM mysql.user;'
echo -en "Enter mysql user name: "
read mysqlUser
endCheckEmpty mysqlDatabase "user name"
echo -en "Enter mysql user password: "
read mysqlPass
endCheckEmpty mysqlPass "password"
mysql -u root -e 'CREATE USER '"'"$mysqlUser"'"'@'"'"'localhost'"'"' IDENTIFIED BY '"'"$mysqlPass"'"';'
saveReturn $?
endReturn
mysql -u root -e 'GRANT ALL PRIVILEGES ON '$mysqlDatabase'.* TO '"'"$mysqlUser"'"'@'"'"'localhost'"'"';'
saveReturn $?
endReturn
mysql -u root -e 'FLUSH PRIVILEGES;'
if [ -f "$SEQ_GITEA_BIN_LOC" ] ; then
local toolBackup="${SEQ_GITEA_BACKUP_DIR}/gitea_${versionNow}"
exe service gitea stop
saveReturn $?
endReturn
echoseq -n "Backing up existing executable to ${toolBackup}..."
exe cp -ar "$SEQ_GITEA_BIN_LOC" "$toolBackup" && echoseq "ok" || echoseq "nok"
fi
exe install --backup=none -m 755 -T "$giteaDownFile" "$SEQ_GITEA_BIN_LOC"
endReturn -o $? "Upgrade failed"
exe service gitea start
}
step_20_info() { echo "Secure settings after installation"; }
step_20() {
chmod 750 /etc/gitea
chmod 644 /etc/gitea/app.ini
exe chmod 750 "$SEQ_GITEA_CONF_DIR"
exe chmod 644 "$giteaIniLoc"
}
# Sequence Revision
VERSION_SEQREV=1
step_22_info() { echo "Open $toolName config file"; }
step_22_alias() { ALIAS="config"; }
step_22() {
exe vi "$giteaIniLoc"
}
# Workaround when called from different directory
# Not needed when path to sequencer is absolut
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
# Path to sequencer
. ${DIR}/../sequencer/sequencer.sh
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

3
seqs/grocy.cfg.example Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash
sc_grocyDir="/var/www/grocy"

166
seqs/grocy.sh Executable file
View File

@@ -0,0 +1,166 @@
#!/usr/bin/env bash
shopt -s extglob
readonly toolName=grocy
readonly downUrl="https://releases.grocy.info/latest"
readonly versionUrl="https://api.github.com/repos/grocy/grocy/releases/latest"
versionNew=
versionNow=
sc_grocyConf=
sc_grocyBackup="data/backup"
sc_grocyViewcache="data/viewcache"
grocyDownLoc="/tmp/grocy_latest.zip"
# Get script working directory
# (when called from a different directory and even when called via symlink)
readonly sq_dir="$(cd "$(dirname -- "$(realpath ${BASH_SOURCE[0]})")" >>/dev/null 2>&1 && pwd)"
readonly sq_scriptFile=$(basename -- $0)
readonly sq_scriptName=${sq_scriptFile%%.*}
readonly sq_configFileName="${sq_scriptName}.cfg"
readonly sq_configFileTemplate="$sq_dir/${sq_configFileName}.example"
sq_aptOpt=
sq_config=0
step_config() {
initSeqConfig -p "$sq_scriptName" "$sq_configFileTemplate"
if [ $? -eq 0 ] ; then
sq_config=1
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return -1
fi
sc_grocyConf="${sc_grocyDir}/data/config.php"
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && sq_aptOpt="-y"
## Return of non zero value will abort the sequence
return 0
}
getVersions() {
versionNew=${versionNew:-$(curl --silent "$versionUrl" | grep -Po '"tag_name": "v\K.*?(?=")')}
versionNow=${versionNow:-$(grep -Po '"Version": "\K.*?(?=")' 2>/dev/null < "${sc_grocyDir}/version.json")}
}
step_1_info() {
echo "Check $toolName status"
echoinfo "Returns 1 if update is available"
}
step_1_alias() { ALIAS="status"; }
step_1() {
getVersions
if [ -e "${sc_grocyDir}" ] ; then
echo
echo "$toolName installed"
echo " at: ${sc_grocyDir}"
echo " version: ${versionNow}"
echo " config: ${sc_grocyConf}"
echo -n " update: "
if [[ ! ${versionNow} = ${versionNew} ]] ; then
echo "available: ${versionNew}}"
return 1
else
echo "already on latest"
return 0
fi
else
echo "$toolName not installed"
echo "Version ${versionNew} available for installation"
return 1
fi
}
step_20_info() { echo "Backup ${toolName}"; }
step_20_alias() { ALIAS="backup"; }
step_20() {
local lBu="${sc_grocyDir}/${sc_grocyBackup}/${toolName}_$(date +%Y%m%d-%H%M%S).tgz"
exe cd ${sc_grocyDir}/..
exe tar \
--exclude="${sc_grocyBackup}/*" \
--exclude="${sc_grocyViewcache}/*" \
-czf "${lBu}" \
"$(basename "${sc_grocyDir}")"
}
step_22_info() { echo "Install/upgrade ${toolName}"; }
step_22_alias() { ALIAS="install"; }
step_22() {
getVersions
if [[ ${versionNow} == ${versionNew} ]] ; then
endReturn -o 1 "Latest version ${versionNow} already installed"
else
if [ -n "${versionNow}" ] ; then
echoseq " [I] Upgrading $toolName from ${versionNow} to ${versionNew}"
else
echoseq " [I] Installing $toolName version ${versionNew}"
fi
fi
exe wget ${downUrl} -q -O "${grocyDownLoc}"
endReturn -o $? "Download failed"
if [ -e "${sc_grocyDir}" ] ; then
step backup
exe rm -rf "${sc_grocyDir}/${sc_grocyViewcache}"
fi
exe rm -rf "${sc_grocyDir}/"!(data)
exe unzip -o -qq "${grocyDownLoc}" -d "${sc_grocyDir}"
exe chown -R www-data: "${sc_grocyDir}/public" "${sc_grocyDir}/data"
# Populate first config
if [ ! -e "${sc_grocyConf}" ] ; then
exe cp "${sc_grocyDir}/config-dist.php" "${sc_grocyConf}"
echoseq " [I] Please adjust the config: ${sc_grocyConf}"
else
echoseq " [I] Please check ${sc_grocyDir}/config-dist.php"
echoseq " for new configuration options"
fi
}
step_30_alias() { ALIAS="notes"; }
step_30() {
outColor green
cat <<NOTES_END
# Behind reverse proxy as subfolder
* Install in the root of a nginx server (e.g. localhost:8080)
* Proxy pass from a subdirectory (e.g. domain.me/grocy)
* [data/config.php]
Setting('BASE_PATH', '');
Setting('BASE_URL', 'https://domain.me/grocy');
# Nginx config
server {
listen 8080;
root /var/www/grocy/public;
index index.php;
#access_log /var/log/nginx/grocy.access.log;
error_log /var/log/nginx/grocy.error.log;
location ~ ^.+?\.php(/.*)?\$ {
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)\$;
set \$path_info \$fastcgi_path_info;
fastcgi_param PATH_INFO \$path_info;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
}
location / {
try_files \$uri /index.php\$is_args\$query_string;
}
}
NOTES_END
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh

145
seqs/jitsi.sh Executable file
View File

@@ -0,0 +1,145 @@
#!/bin/bash
toolName="jitsi-meet"
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
#CONFIG=0
#CONFIG_FILE_NAME="${toolName}.cfg"
#CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
#step_config() {
#echo "Called once before executing steps."
## e.g. to source a config file manually:
#. "$CONFIG_FILE"
## or to use sequencer api:
#initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
#if [ $? -eq 0 ] ; then
# CONFIG=1
#fi
#}
step_1_info() { echo "Installation of prerequisits"; }
step_1_alias() { ALIAS="prepare"; }
step_1() {
exe apt install gnupg2 git lsb-release ssl-cert ca-certificates apt-transport-https \
tree locate software-properties-common dirmngr screen htop nano net-tools zip unzip \
curl ffmpeg ghostscript libfile-fcntllock-perl curl socat
}
step_2_info() { echo "Add universe and official nginx apt repositories"; }
step_2() {
apt-add-repository universe
exep "echo \"deb [arch=amd64] http://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx\" | tee /etc/apt/sources.list.d/nginx.list"
exep "curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -"
}
step_3_info() { echo "Add official $toolName apt repository"; }
step_3() {
exep "echo \"deb https://download.jitsi.org stable/\" | tee /etc/apt/sources.list.d/jitsi.list"
exep "wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | sudo apt-key add -"
}
step_4_info() { echo "Upgrade system packages"; }
step_4() {
exe apt update && apt upgrade
}
step_5_info() { echo "Install nginx webserver"; }
step_5_alias() { ALIAS="webserver"; }
step_5() {
exe apt install nginx
endReturn -o $? "Installation of webserver nginx failed"
exe mkdir -p /etc/nginx/sites-available
exe mkdir -p /etc/nginx/sites-enabled
exe mkdir -p /etc/nginx/modules-enabled
exe systemctl enable nginx.service
}
step_6_info() { echo "Install ufw firewall"; }
step_6_alias() { ALIAS="firewall"; }
step_6() {
exe apt install ufw
endReturn -o $? "Installation of firewall ufw failed"
}
step_7_info() { echo "Setup ufw firewall to run $toolName"; }
step_7() {
echo " [I] Configure ufw firewall"
exe ufw allow 22/tcp
exe ufw allow 80/tcp
exe ufw allow 443/tcp
exe ufw allow 4443/tcp
exe ufw allow 10000/udp
exe ufw logging medium && ufw default deny incoming && ufw enable && service ufw restart
}
step_8_info() { echo "Install $toolName"; }
step_8_alias() { ALIAS="install"; }
step_8() {
exe read -p "Make sure SSL certificates are available. Enter to continue"
exe apt install jitsi-meet -y
}
step_9_info() { echo "Move automatically generated $toolName virutal host to new configuration directory"; }
step_9() {
exe mv /etc/nginx/sites-available/*.conf /etc/nginx/conf.d
exe mv /etc/nginx/conf.d/default.conf /etc/nginx/sites-available
exe service nginx restart
echo " [I] Check /etc/nginx/conf.d for unwanted configurations"
}
step_10_info() { echo "WIP post-install tasks"; }
step_10() {
echo " [I] Tasks to be automated"
echo
echo " * Make jitsi installation password protected"
echo " (https://github.com/jitsi/jicofo#secure-domain)"
echo " Creating new rooms will require username and password"
echo
echo " ** /etc/prosody/conf.avail/[your-hostname].cfg.lua"
echo
echo " a) Enable authentication on your main domain:"
echo
echo " VirtualHost \"jitsi-meet.example.com\""
echo " authentication = \"internal_plain\""
echo
echo " b) Add new virtual host with anonymous login method for guests:"
echo
echo " VirtualHost \"guest.jitsi-meet.example.com\""
echo " authentication = \"anonymous\""
echo " c2s_require_encryption = false"
echo
echo " ** /etc/jitsi/meet/[your-hostname]-config.js"
echo
echo " var config = {"
echo " hosts: {"
echo " domain: 'jitsi-meet.example.com',"
echo " anonymousdomain: 'guest.jitsi-meet.example.com',"
echo " ..."
echo " },"
echo " ..."
echo " }"
echo
echo " ** /etc/jitsi/jicofo/sip-communicator.properties"
echo " add new line:"
echo
echo " org.jitsi.jicofo.auth.URL=XMPP:jitsi-meet.example.com"
echo
echo " ** Create prosody user(s):"
echo
echo " prosodyctl register <username> jitsi-meet.example.com <password>"
echo
echo " [I] Use step \"restart\" after these changes"
}
step_20_info() { echo "Restart all $toolName components"; }
step_20_alias() { ALIAS="restart"; }
step_20() {
echo " [I] Restart jitsi-meet components"
exep "service prosody restart&& service jicofo restart && service jitsi-videobridge2 restart"
}
VERSION_SEQREV=10
. /usr/local/bin/sequencer.sh

196
seqs/kodi.sh Executable file
View File

@@ -0,0 +1,196 @@
#!/bin/bash
## Installing kodi on a raspberry pi
## Some measures are taken to prevent corrupting existing files
## but it's intendet use is for a blank rasperry pi.
toolName="Kodi"
toolUser="kodi"
toolServiceFile="/etc/systemd/system/kodi.service"
toolProfileDir="/home/kodi/.kodi"
step_1_info() { echo "Install $toolName via apt"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update && apt install kodi
}
step_2_info() { echo "Set localisation and keyboard layout"; }
step_2() {
echo "Goto \"Localisation Options\" in the following menu."
read -p "Press ENTER to continue..."
exe raspi-config
saveReturn $?
endReturn
}
step_3_info() { echo "Add $toolName user ($toolUser)"; }
step_3() {
exep "id -u $toolUser >>/dev/null 2>&1"
if [ $? -eq 0 ] ; then
echo
echo "User $toolUser exists."
echo "Skipping user creation."
return 0
fi
exe adduser \
--disabled-password \
--gecos "User to run $toolName Media Center" \
$toolUser
exe usermod -a -G audio,video,plugdev,input,tty $toolUser
saveReturn $?
endReturn
echo "User $toolUser details:"
exe id $tooLuser
}
step_4_info() { echo "Create systemd service"; }
step_4() {
addConf -c "$toolServiceContent" "$toolServiceFile"
if [ $? -eq 0 ] ; then
exe systemctl daemon-reload
exe systemctl enable kodi.service
saveReturn $?
endReturn
else
echo "[ERROR] failed to setup systemd service"
fi
}
toolServiceContent="\
[Unit]
Description = Kodi Media Center
# if you don't need the MySQL DB backend, this should be sufficient
After = systemd-user-sessions.service network.target sound.target
# if you need the MySQL DB backend, use this block instead of the previous
# After = systemd-user-sessions.service network.target sound.target mysql.service
# Wants = mysql.service
[Service]
User = kodi
Group = kodi
Type = simple
ExecStart = /usr/bin/kodi-standalone
Restart = always
RestartSec = 15
[Install]
WantedBy = multi-user.target"
step_5_info() { echo "Enable text input for USB keyboards within $toolName"; }
step_5() {
local udevFile="/etc/udev/rules.d/99-kodi.rules"
local inputRule="KERNEL==\"tty[0-9]*\", GROUP=\"tty\", MODE=\"0660\""
addConf -c "$inputRule" "$udevFile"
}
step_6_info() { echo "Increase raspberry pi GPU memory to 320"; }
step_6() {
exep "grep -e '^[ ]*gpu_mem' \"$bootConfigLoc\" >>/dev/null 2>&1"
if [ $? -ne 0 ] && [ -f "$bootConfigLoc" ] ; then
# attach settings to raspberry boot configuration
exe mount -o remount,rw /boot
addConf -a "$bootConfig" "$bootConfigLoc"
exe mount -o remount,ro /boot
else
# add to missing conf
addConf -m "$bootConfig" "$bootConfigLoc"
fi
}
bootConfigLoc="/boot/config.txt"
bootConfig="
# Modifications for $toolName
start_x=1
gpu_mem=320"
step_7_info() { echo "Reboot is needed for all changes to take effect"; }
step_7() {
if [ $QUIET -eq "1" ] ; then
answer=n
else
read -p "Reboot now? y/n(default)" answer
fi
case $answer in
y|Y)
exe reboot;;
*)
echo
echo "Start $toolName manually:"
echo "service kodi start"
;;
esac
}
step_10_info() { echo "Send $toolName logs to syslog"; }
step_10_alias() { ALIAS="syslog"; }
step_10() {
addConf -s "$kodiSyslog" "$kodiSyslogLoc"
exe chmod -f +x "$kodiSyslogLoc"
}
kodiSyslogLoc="/usr/local/bin/kodisyslog"
kodiSyslog="#!/bin/bash
tail -f /home/kodi/.kodi/temp/kodi.log |
while read -r line
do
logger -t KODI \"\${line:37}\"
done"
step_11_info() { echo "Create systemd service for logging to syslog"; }
step_11() {
[ ! -f "$kodiSyslogLoc" ] && return 1
addConf -s "$kodiSyslogService" "$kodiSyslogServiceLoc"
echoseq " [I] Consider limiting systemd journal size"
echoseq " [/etc/systemd/journald.conf]"
echoseq " SystemMaxUse=50M"
}
kodiSyslogServiceLoc="/etc/systemd/system/kodisyslog.service"
kodiSyslogService="[Unit]
Description=Pipe kodi logs to syslog
After=network.target syslog.service
[Service]
User=root
ExecStart=/usr/local/bin/kodisyslog
[Install]
WantedBy=multi-user.target"
step_12_info() { echo "Enable and start kodisyslog service"; }
step_12() {
local kodiSyslogName="$(basename $kodiSyslogServiceLoc)"
exe systemctl daemon-reload
exe systemctl enable $kodiSyslogName
exe systemctl start $kodiSyslogName
}
step_40_info() { echo "Reset music database"; }
step_40_alias() { ALIAS="resetmusic"; }
step_40() {
local i
local answer="y"
local musicDb=( "$toolProfileDir/userdata/Database/MyMusic"*.db )
echoseq " [W] Erasing:"
for i in ${musicDb[@]}; do
echoseq $i
done
[ $QUIET -eq 0 ] && read -p "Are you sure? (y)/[n] " answer
case "$answer" in
y|Y)
exe rm ${musicDb[@]};;
*)
echoseq " [I] Abort reset"
return 1;
esac
}
VERSION_SEQREV=12
. /usr/local/bin/sequencer.sh

11
seqs/ldap.cfg.example Normal file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
# Configuration options for ldap installation and management
LDAP_DC="dc=winklerfamilie,dc=eu"
LDAP_OU_GROUPS="ou=Groups"
LDAP_OU_USERS="ou=Users"
LDAP_CERT="/etc/letsencrypt/live/winklerfamilie.eu/cert.pem"
LDAP_CERT_KEY="/etc/letsencrypt/live/winklerfamilie.eu/privkey.pem"
LDAP_CERT_CA="/etc/letsencrypt/live/winklerfamilie.eu/fullchain.pem"

368
seqs/ldap.sh Executable file
View File

@@ -0,0 +1,368 @@
#!/bin/bash
toolName="ldap"
toolDaemon="slapd"
toolDeps="$toolDaemon ldap-utils"
toolUser="openldap"
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="${toolName}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
fi
}
step_1_info() { echo "$toolName installation"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
exe apt install $toolDeps
}
step_2_info() { echo "Configuration of $toolName"; }
step_2() {
exe dpkg-reconfigure $toolDaemon
}
step_3_info() { echo "Load memberof module"; }
step_3() {
local tempLdif=`eval "echo \"$loadMemberof\""`
exep "echo \"$tempLdif\" | ldapmodify -Q -Y EXTERNAL -H ldapi:///"
}
loadMemberof="dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: memberof.la
"
step_4_info() { echo "Configure memberof module"; }
step_4() {
local tempLdif=`eval "echo \"$configMemberof\""`
exep "echo \"$tempLdif\" | ldapadd -Q -Y EXTERNAL -H ldapi:///"
}
configMemberof="dn: olcOverlay=memberof,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcMemberOf
olcOverlay: memberof
olcMemberOfRefint: TRUE
-
dn: olcDatabase={1}mdb,cn=config
olcDbIndex: memberOf eq
"
step_5_info() { echo "Load refint module"; }
step_5() {
local tempLdif=`eval "echo \"$loadRefint\""`
exep "echo \"$tempLdif\" | ldapmodify -Q -Y EXTERNAL -H ldapi:///"
}
loadRefint="dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: refint.la
"
step_6_info() { echo "Configure refint module"; }
step_6() {
local tempLdif=`eval "echo \"$configRefint\""`
exep "echo \"$tempLdif\" | ldapadd -Q -Y EXTERNAL -H ldapi:///"
}
configRefint="dn: olcOverlay={1}refint,olcDatabase={1}mdb,cn=config
objectClass: olcConfig
objectClass: olcOverlayConfig
objectClass: olcRefintConfig
objectClass: top
olcOverlay: {1}refint
olcRefintAttribute: memberof member manager owner
"
step_7_info() { echo "Create base DNs for users ($LDAP_OU_USERS) and groups ($LDAP_OU_GROUPS)"; }
step_7() {
variable2Ldif add "$ldapBase"
}
ldapBase="dn: \$LDAP_OU_USERS,\$LDAP_DC
objectClass: organizationalUnit
\${LDAP_OU_USERS/ou=/ou: }
dn: \$LDAP_OU_GROUPS,\$LDAP_DC
objectClass: organizationalUnit
\${LDAP_OU_GROUPS/ou=/ou: }
"
step_8_info() { echo "Setup SSL secured ldaps:// access"; }
step_8() {
sudo -u $toolUser test -r "$LDAP_CERT_KEY" >>/dev/null 2>&1
endReturn -o $? "$toolUser cannot access certificate key file: $LDAP_CERT_KEY"
sudo -u $toolUser test -r "$LDAP_CERT" >>/dev/null 2>&1
endReturn -o $? "$toolUser cannot access certificate file: $LDAP_CERT"
sudo -u $toolUser test -r "$LDAP_CERT_CA" >>/dev/null 2>&1
endReturn -o $? "$toolUser cannot access CA certificate file: $LDAP_CERT_CA"
local tempLdif=`eval "echo \"$sslSetup\""`
exep "echo \"$tempLdif\" | ldapmodify -Y EXTERNAL -H ldapi:///"
exe service $toolDaemon restart
}
sslSetup="dn: cn=config
changetype: modify
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: \$LDAP_CERT_KEY
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: \$LDAP_CERT
-
replace: olcTLSCACertificateFile
olcTLSCACertificateFile: \$LDAP_CERT_CA
-
replace: olcTLSVerifyClient
olcTLSVerifyClient: never
"
step_9_info() { echo "Finalize SSL configuration (manually)"; }
step_9() {
echo "/etc/default/$toolDaemon"
echo " Add \"ldaps:///\" to line:"
echo " SLAPD_SERVICES=\"ldap:/// ldaps:/// ldapi:///\""
echo
}
step_20_info() { echo "Test plain ldap connection with anonymous access"; }
step_20() {
exe ldapwhoami -H ldapi:/// -x
}
step_80_info() { echo -e "Some ldap command notes\n"; }
step_80_alias() { ALIAS="notes"; }
step_80() {
outColor green
cat <<NOTES_EOF
# You can also check LDAP Base DN using the ldapsearch command as shown below
ldapsearch -H ldapi:/// -x -LLL -s base -b "" namingContexts
# To view the RootDN, run the command below
ldapsearch -H ldapi:/// -Y EXTERNAL -b "cn=config" "(olcRootDN=*)"
# Reset root password
## Create a password hash {SSHA}....
slappasswd
## Modify olcRootPW
ldapmodify -Q -Y EXTERNAL -H ldapi:/// << E0F
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: {SSHA}thehashyoucreatedabove
E0F
NOTES_EOF
}
step_100_info() { echo "Add group <GROUP NAME> <USER ID>"; }
step_100_alias() { ALIAS="addgroup"; }
step_100() {
shift
local groupName=$1
local memberDn="uid=$2,${LDAP_OU_USERS},${LDAP_DC}"
variable2Ldif add "$addGroup"
}
addGroup="dn: cn=\${groupName},\${LDAP_OU_GROUPS},\${LDAP_DC}
objectClass: groupofnames
cn: \${groupName}
description: Created by $0
member: \${memberDn}
"
step_102_info() { echo "Add user <USER ID> <USER NAME> <USER LASTNAME> <UIDNUMBER> <USER EMAIL> [USER GID]"; }
step_102_alias() { ALIAS="adduser"; }
step_102() {
shift
userId="$1"
local userCn="$2 $3"
local givenName="$2"
local userSn="$3"
local uidNumber="$4"
local userMail="$5"
local userGid=10000
if [ ! -z $6 ] ; then
userGid="$6"
fi
variable2Ldif add "$addUser"
endReturn -o $? "Adding user failed"
}
userId=
addUser="dn: uid=\$userId,\$LDAP_OU_USERS,\$LDAP_DC
cn: \$userCn
givenName: \$givenName
sn: \$userSn
uid: \$userId
uidNumber: \$uidNumber
gidNumber: \$userGid
homeDirectory: /home/\$userId
mail: \$userMail
objectClass: top
objectClass: posixAccount
objectClass: shadowAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
loginShell: /bin/bash
"
step_103_info() { echo "(re)Set passwort for <USER>"; }
step_103_alias() { ALIAS="passwd"; }
step_103() {
shift
if [ ! -z $1 ] ; then
echo " [I] Password operation for $1"
userId="$1"
elif [ ! -z $userId ] ; then
echo " [I] Password operation for $userId"
else
echoerr " [E] No user id provided"
return 1
fi
exe ldappasswd -H ldapi:/// -x -D "cn=admin,$LDAP_DC" -W -S "uid=$userId,$LDAP_OU_USERS,$LDAP_DC"
}
step_105_info() { echo "Adding <USER ID> to existing group <GROUP NAME>"; }
step_105_alias() { ALIAS="user2group"; }
step_105() {
shift
if [ ! -z $1 ] ; then
userId="$1"
echo " [I] User operation for $userId"
elif [ ! -z $userId ] ; then
echo " [I] User operation for $userId"
else
echoerr " [E] No user id provided"
return 1
fi
if [ -z $2 ] ; then
echoerr " [E] No group name provided"
return 2
fi
local groupName="$2"
variable2Ldif modify "$removeFromgroup"
variable2Ldif modify "$add2group"
endReturn -o $? "Adding user to group failed"
}
#remove empty member
add2group="dn: cn=\$groupName,\$LDAP_OU_GROUPS,\$LDAP_DC
changetype: modify
add: member
member: uid=\$userId,\$LDAP_OU_USERS,\$LDAP_DC
dn: cn=\$groupName,\$LDAP_OU_GROUPS,\$LDAP_DC
changetype: modify
delete: member
member:
"
step_107_info() { echo "Removing <USER ID> from existing group <GROUP NAME>"; }
step_107_alias() { ALIAS="rmusergroup"; }
step_107() {
shift
if [ ! -z $1 ] ; then
userId="$1"
echo " [I] User operation for $userId"
elif [ ! -z $userId ] ; then
echo " [I] User operation for $userId"
else
echoerr " [E] No user id provided"
return 1
fi
if [ -z $2 ] ; then
echoerr " [E] No group name provided"
return 2
fi
local groupName="$2"
variable2Ldif modify "$removeFromgroup"
}
# try to delete user entry first to ensure correct memberof status
# make sure an empty member entry exists
removeFromgroup="dn: cn=\$groupName,\$LDAP_OU_GROUPS,\$LDAP_DC
changetype: modify
add: member
member:
dn: cn=\$groupName,\$LDAP_OU_GROUPS,\$LDAP_DC
changetype: modify
delete: member
member: uid=\$userId,\$LDAP_OU_USERS,\$LDAP_DC
"
step_110_info() { echo "Remove group <GROUP NAME>"; }
step_110_alias() { ALIAS="rmgroup"; }
step_110() {
shift
if [ -z $1 ] ; then
echoerr " [E] No group name provided"
return 1
fi
local groupName=$1
variable2Ldif modify "$rmGroup"
}
rmGroup="dn: cn=\${groupName},\${LDAP_OU_GROUPS},\${LDAP_DC}
changetype: delete
"
step_112_info() { echo "Remove user <USER ID>"; }
step_112_alias() { ALIAS="rmuser"; }
step_112() {
shift
if [ -z $1 ] ; then
echoerr " [E] No user id provided"
return 1
fi
local userName=$1
variable2Ldif modify "$rmUser"
}
rmUser="dn: uid=\${userName},\${LDAP_OU_USERS},\${LDAP_DC}
changetype: delete
"
step_200_info() { echo "List available groups <ADDITONAL ATTRIBUTES...>"; }
step_200_alias() { ALIAS="listgroups"; }
step_200() {
shift
echo " [I] Available groups:"
exe ldapsearch -x -LLL -H ldap:/// -b ${LDAP_OU_GROUPS},${LDAP_DC} dn gidNumber $*
}
step_202_info() { echo "List available users <ADDITONAL ATTRIBUTES...>"; }
step_202_alias() { ALIAS="listusers"; }
step_202() {
shift
echo " [I] Available user:"
exe ldapsearch -x -LLL -H ldap:/// -b ${LDAP_OU_USERS},${LDAP_DC} dn uidNumber gidNumber $*
}
variable2Ldif() {
local cmd="ldapmodify"
local tempLdif=`eval "echo \"$2\""`
case $1 in
add)
cmd="ldapadd"
;;
delete)
cmd="ldapdelete"
;;
esac
exep "echo \"$tempLdif\" | $cmd -x -D cn=admin,${LDAP_DC} -W"
}
variable2LdifEcho() {
local tempLdif=`eval "echo \"$2\""`
echo "$tempLdif"
}
VERSION_SEQREV=10
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,5 @@
#!/bin/bash
LNMS_DIR="/opt/librenms"
LNMS_BU_DIR="/root/backup/librenms"
LNMS_DB_NAME="librenms_db"

View File

@@ -2,141 +2,278 @@
#
## Installation and maintenance for LibreNMS
## Using buster repositories for php 7.3 installation
toolName="LibreNMS"
librePhpDeps="composer php-cli-prompt php-composer-ca-bundle php-composer-semver php-composer-spdx-licenses php-json-schema php-psr-log php-symfony-console php-symfony-filesystem php-symfony-finder php-symfony-polyfill-mbstring php-symfony-process"
librePackages="fping git graphviz imagemagick mtr-tiny nmap python-memcache python-mysqldb rrdtool snmp snmpd whoisi nagios-plugins"
toolName="librenms"
toolUser="librenms"
phpVersion=
libreDeps='acl curl composer fping git graphviz imagemagick mtr-tiny nmap rrdtool snmp snmpd whois python3-dotenv python3-pymysql python3-redis python3-setuptools'
librePhpDeps='php${phpVersion}-cli php${phpVersion}-curl php${phpVersion}-fpm php${phpVersion}-gd php${phpVersion}-json php${phpVersion}-mbstring php${phpVersion}-mysql php${phpVersion}-snmp php${phpVersion}-xml php${phpVersion}-zip'
#librePhpDeps="composer php-cli-prompt php-composer-ca-bundle php-composer-semver php-composer-spdx-licenses php-json-schema php-psr-log php-symfony-console php-symfony-filesystem php-symfony-finder php-symfony-polyfill-mbstring php-symfony-process"
#librePackages="fping git graphviz imagemagick mtr-tiny nmap python-memcache python-mysqldb rrdtool snmp snmpd whoisi nagios-plugins"
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd )"
CONFIG=0
SCRIPT_NAME=$(basename -- "$0")
SCRIPT_NAME=${SCRIPT_NAME%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
echoseq " Install: $LNMS_DIR"
echoseq " Backup: $LNMS_BU_DIR"
else
[ $DRY -eq 0 ] && return 1
fi
}
step_1_info() { echo "Updating apt"; }
step_1_alias() { ALIAS="install"; }
step_1() {
apt update
exe apt update
}
step_2_info() { echo -e "Installing $toolname dependencies: $librePackages\n"; }
step_2_info() {
echo "Installing $toolname dependencies:"
echoinfo "$libreDeps"
}
step_2() {
apt install $librePackages
saveReturn $?
endReturn
exe apt install $libreDeps
endReturn -o $? "Failed to install $toolName dependencies"
}
step_3_info() { echo -e "Installing -t buster PHP related packages\n$librePhpDeps\n"; }
step_3_info() {
echo "Installing PHP related packages:"
fetchPhpVersion
echoinfo `eval echo "$librePhpDeps"`
}
step_3() {
apt -t buster install $librePhpDeps
saveReturn $?
endReturn
fetchPhpVersion
exe apt install `eval echo "$librePhpDeps"`
endReturn -o $? "Failed to install $toolName php dependencies"
}
step_4_info() { echo "Adding $toolName user (librenms:librenms)"; }
step_4_info() { echo "Adding $toolName user ($toolUser)"; }
step_4() {
useradd librenms -d /opt/librenms -M -r
exe useradd $toolUser -d "$LNMS_DIR" -M -r -s "$(which bash)"
saveReturn $?
usermod -a -G librenms www-data
saveReturn $?
endReturn
#exe usermod -a -G librenms www-data
#saveReturn $?
endReturn "Failed to create user $toolUser"
}
step_5_info() { echo "Installing $toolName using composer"; }
step_5_info() { echo "Clone $toolName git repository"; }
step_5() {
cd /opt
composer create-project --no-dev --keep-vcs librenms/librenms librenms dev-master
saveReturn $?
endReturn
exe git clone https://github.com/librenms/librenms.git "$LNMS_DIR"
# set permissions
step fix
}
step_6_info() { echo "Installing $toolName using composer"; }
step_6() {
exe sudo -u librenms "${LNMS_DIR}/scripts/composer_wrapper.php" install --no-dev
endReturn -o $? "Failed to install php dependencies"
}
step_10_info() { echo "Create mysql database for $toolName"; }
step_10() {
local mysqlDatabase
local mysqlUser
local mysqlPass
echo "Existing mysql databases:"
mysql -u root -e 'SHOW DATABASES;'
echo -en "Enter database name: "
read mysqlDatabase
endCheckEmpty mysqlDatabase "database name"
mysql -u root -e 'CREATE DATABASE '$mysqlDatabase' CHARACTER SET utf8 COLLATE utf8_unicode_ci;'
saveReturn $?
endReturn
echo "Existing mysql user:"
mysql -u root -e 'SELECT User, Host FROM mysql.user;'
echo -en "Enter mysql user name: "
read mysqlUser
endCheckEmpty mysqlDatabase "user name"
echo -en "Enter mysql user password: "
read mysqlPass
endCheckEmpty mysqlPass "password"
mysql -u root -e 'CREATE USER '"'"$mysqlUser"'"'@'"'"'localhost'"'"' IDENTIFIED BY '"'"$mysqlPass"'"';'
saveReturn $?
endReturn
mysql -u root -e 'GRANT ALL PRIVILEGES ON '$mysqlDatabase'.* TO '"'"$mysqlUser"'"'@'"'"'localhost'"'"';'
saveReturn $?
endReturn
mysql -u root -e 'FLUSH PRIVILEGES;'
local libreDbOpt=
if [ ! -z "$LNMS_DB_NAME" ] ; then
libreDbOpt="-d $LNMS_DB_NAME"
fi
exe ${WDIR}/mysql.sh -q createdb --charset utf8 $libreDbOpt
endReturn -o $? "Failed to create mysql database $LNMS_DB_NAME"
}
step_11_info() { echo "MariaDB configuration"; }
step_11() {
echo
echo "Edit or create /etc/mysql/mariadb.conf.d/90-myconfig.cnf and add:"
echo
echo "------------------------"
echo "[mysqld]"
echo "innodb_file_per_table=1"
echo "lower_case_table_names=0"
echo "------------------------"
echo
echo "Restart mysql afterwards:"
echo "service mysql restart"
outColor green
cat << SQLCONF_END
Edit or create /etc/mysql/mariadb.conf.d/90-myconfig.cnf and add:
------------------------
[mysqld]
innodb_file_per_table=1
lower_case_table_names=0
------------------------
Restart mysql afterwards:
service mysql restart
SQLCONF_END
}
step_12_info() { echo "PHP fpm/cli configuration"; }
step_12_info() { echo "PHP fpm/cli timezone configuration"; }
step_12() {
echo
echo "Ensure date.timezone is set in php.ini to your preferred time zone. See http://php.net/manual/en/timezones.php for a list of supported timezones. Valid examples are: \"America/New_York\", \"Europe/Berlin\", \"Etc/UTC\"."
echo
echo "vi /etc/php/7.3/fpm/conf.d/90-custom_pi.ini"
echo "vi /etc/php/7.3/cli/php.ini"
echo
echo "-------------------------------------------"
echo "date.timezone = Europe/Berlin"
echo "-------------------------------------------"
echo
echo "Restart php-fpm afterwards:"
echo "service php7.3-fpm restart"
outColor green
cat << PHPCONF_END
Ensure date.timezone is set in php.ini to your preferred time zone. See http://php.net/manual/en/timezones.php for a list of supported timezones. Valid examples are: "America/New_York", "Europe/Berlin", "Etc/UTC".
vi /etc/php/7.3/fpm/conf.d/90-custom_pi.ini
vi /etc/php/7.3/cli/conf.d/90-custom_pi.ini
-------------------------------------------
date.timezone = Europe/Berlin
-------------------------------------------
Restart php-fpm afterwards:
service php7.3-fpm restart
PHPCONF_END
}
step_13_info() { echo "PHP fpm configuration"; }
step_13() {
outColor green
cat << FPMCONF_END
cp /etc/php/7.3/fpm/pool.d/www.conf /etc/php/7.3/fpm/pool.d/librenms.conf
vi /etc/php/7.3/fpm/pool.d/librenms.conf
# Change [www] to [librenms]:
[librenms]
# Change user and group to "librenms":
user = librenms
group = librenms
# Change listen to a unique name:
listen = /run/php-fpm-librenms.sock
FPMCONF_END
}
step_14_info() { echo "Nginx configuration"; }
step_14() {
outColor green
cat << NGINXCONF_END
server {
listen 80;
server_name librenms.example.com;
root $LNMS_DIR/html;
index index.php;
charset utf-8;
gzip on;
gzip_types text/css application/javascript text/javascript application/x-javascript image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon;
location / {
try_files \$uri \$uri/ /index.php?\$query_string;
}
location ~ [^/]\\.php(/|$) {
fastcgi_pass unix:/run/php-fpm-librenms.sock;
fastcgi_split_path_info ^(.+\\.php)(/.+)$;
include fastcgi.conf;
}
location ~ /\\.(?!well-known).* {
deny all;
}
}
NGINXCONF_END
}
step_20_info() { echo "Create $toolName cron job"; }
step_20_alias() { ALIAS="cron"; }
step_20() {
echoseq -n " [I] Creating $lnmsCronLoc ... "
exe cp "${LNMS_DIR}/librenms.nonroot.cron" "$lnmsCronLoc" && echoseq "Ok" || echoseq "Nok"
}
lnmsCronLoc="/etc/cron.d/librenms"
step_22_info() { echo "Enable lnms command completion"; }
step_22_alias() { ALIAS="cmdcompletion"; }
step_22() {
exep 'echo -e "#!/bin/bash\nsudo -u '$toolUser' \"'$LNMS_DIR'/lnms\" \"\$@\"" > '"$lnmsLocalBin"
exe chmod 744 "$lnmsLocalBin"
exe cp "${LNMS_DIR}/misc/lnms-completion.bash" /etc/bash_completion.d/
}
lnmsLocalBin="/usr/local/bin/lnms"
step_24_info() { echo "Copy logrotate config"; }
step_24_alias() { ALIAS="logrotate"; }
step_24() {
echoseq -n " [I] Creating $lnmsLogrotLoc ... "
exe cp "${LNMS_DIR}/misc/librenms.logrotate" "$lnmsLogrotLoc" && echoseq "Ok" || echoseq "Nok"
}
lnmsLogrotLoc="/etc/logrotate.d/librenms"
step_26_info() { echo "Install nagios plugin to enable services"; }
step_26_alias() { ALIAS="services"; }
step_26() {
exe apt install monitoring-plugins
echoseq
echoseq " [$LNMS_DIR/config.php]"
echoseq "\$config['show_services'] = 1;"
echoseq
echoseq " [/etc/cron.d/librenms]"
echoseq " */5 * * * * librenms /opt/librenms/services-wrapper.py 1"
}
step_30_info() { echo "Backup ${toolName} web direcotry"; }
step_30_alias() { ALIAS="backup"; }
step_30() {
echoseq " [I] Backup install directory to ${LNMS_BU_DIR}"
exe mkdir -p "$LNMS_BU_DIR"
exep "cd \"${LNMS_DIR}\"/.. && tar czf \"${LNMS_BU_DIR}/\`date +%Y%m%d\`_${toolName}_web.tar.gz\" \"$(basename "$LNMS_DIR")\""
}
step_31_info() { echo "Backup ${toolName} database [daily|monthly(default)]"; }
step_31_alias() { ALIAS="backupdb"; }
step_31() {
case "$2" in
daily|Daily|DAILY)
echoseq " [I] Daily backup..."
exep "mysqldump --single-transaction -u root ${LNMS_DB_NAME} | bzip2 -c > \"${LNMS_BU_DIR}/${toolName}_daily.sql.bz2\""
;;
*)
exe mkdir -p "$LNMS_BU_DIR/monthly"
echoseq " [I] Monthly backup..."
exep "mysqldump --single-transaction -u root ${LNMS_DB_NAME} | bzip2 -c > \"${LNMS_BU_DIR}/monthly/\`date +%Y%m%d\`_${toolName}.sql.bz2\""
;;
esac
}
step_40_info() { echo "Switch $toolName installation to monthly stable"; }
step_40() {
echo
echo "Add following to /opt/librenms/config.php"
echo
echo "--------------------------------------"
echo "\$config['update_channel'] = 'release';"
echo "--------------------------------------"
echo
echo "Execute following command afterwards:"
echo "cd /opt/librenms && git fetch --tags && git checkout \$(git describe --tags \$(git rev-list --tags --max-count=1))"
cat << STABLE_EOF
Add following to ${LNMS_DIR}/config.php
--------------------------------------
\$config['update_channel'] = 'release';
--------------------------------------
Execute following command afterwards:
cd $LNMS_DIR && git fetch --tags && git checkout \$(git describe --tags \$(git rev-list --tags --max-count=1))
STABLE_EOF
}
step_42_info() { echo "Fix librenms permission"; }
step_42_alias() { ALIAS="fix"; }
step_42() {
chown -R librenms:librenms /opt/librenms
setfacl -d -m g::rwx /opt/librenms/bootstrap/cache /opt/librenms/storage /opt/librenms/logs /opt/librenms/rrd
chmod -R ug=rwX /opt/librenms/bootstrap/cache /opt/librenms/storage /opt/librenms/logs /opt/librenms/rrd
exe chown -R ${toolUser}: "$LNMS_DIR"
exe chmod 771 "${LNMS_DIR}"
exe setfacl -d -m g::rwx "${LNMS_DIR}/rrd" "${LNMS_DIR}/logs" "${LNMS_DIR}/bootstrap/cache/" "${LNMS_DIR}/storage/"
exe setfacl -R -m g::rwx "${LNMS_DIR}/rrd" "${LNMS_DIR}/logs" "${LNMS_DIR}/bootstrap/cache/" "${LNMS_DIR}/storage/"
}
fetchPhpVersion() {
if [ ! -z $phpVersion ] ; then
return 0
fi
phpVersion="$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')"
}
# Sequence Revision
VERSION_SEQREV=1
# Workaround when called from different directory
# Not needed when path to sequencer is absolut
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
# Path to sequencer
. ${DIR}/../sequencer/sequencer.sh
VERSION_SEQREV=12
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,21 @@
#!/bin/bash
# MAS = Mail Server
MAS_DOMAIN="mydomain.com"
MAS_RELAYHOST=
MAS_RELAYUSER=
MAS_RELAYPASS=
MAS_DBUSER='pfa'
MAS_DBPASS='pass'
MAS_DBNAME='pfa_db'
MAS_mysql_virtual_domains_maps="user = '\$MAS_DBUSER'
password = '\$MAS_DBPASS'
hosts = localhost
dbname = '\$MAS_DBNAME'
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
#query = SELECT domain FROM domain WHERE domain='%s'
#optional query to use when relaying for backup MX
#query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
#expansion_limit = 100"

466
seqs/mailserver.sh Executable file
View File

@@ -0,0 +1,466 @@
#!/bin/bash
# Installing a mailserver including postfix postfixadmin and dovecot
#
# MTA = Mail Transport Agent (postfix)
# MDA = Mail Delivery Agent (dovecot)
# MUA = Mail User Agent (Mail program used by the user)
toolName=mailserver
mtaName=postfix
mtaUser=postfix
mtaDeps="$mtaName $mtaName-mysql"
mtaConfLoc="/etc/$mtaName"
mtaMysqlConfLoc="$mtaConfLoc/sql"
mdaName=dovecot
mdaConfLoc="/etc/$mdaName"
mdaConfDir="$mdaConfLoc/conf.d"
mdaDeps="dovecot-imapd dovecot-lmtpd dovecot-mysql dovecot-managesieved dovecot-sieve"
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="${toolName}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
if [ $(id -u) -ne 0 ] ; then
endReturn -o 1 "No root"
fi
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
echoseq " Domain: $MAS_DOMAIN"
elif [ $? -eq 1 ] ; then
# Config $CONFIG_FILE_NAME created. Needs modification first
[ $DRY -eq 0 ] && return -1
fi
return 0
}
step_1_info() { echo "Update apt repositories"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
}
step_2_info() { echo "Install $mtaName"; }
step_2() {
local aptOpt=
if [ $QUIET -ne 0 ];then
aptOpt="-y"
else
read -p "In the following dialog chose \"Internet site\" and enter $MAS_DOMAIN as your domain. Enter to continue..."
fi
exe apt install $mtaDeps $aptOpt
}
step_3_info() { echo "Enable $mtaName"; }
step_3() {
exe systemctl enable $mtaName
echo -e " [I] Printing $mtaName status\n"
exe service $mtaName status
echo -e "\n [I] Installed postfix version: $(postconf mail_version)"
}
step_4_info() { echo "$mtaName basic domain configuration"; }
step_4() {
exe postconf -e "myhostname = mail.$MAS_DOMAIN"
exe postconf -e "mydomain = $MAS_DOMAIN"
exe postconf -e "myorigin = $MAS_DOMAIN"
exe postconf -e "mydestination = $MAS_DOMAIN, \$myhostname, mail.\$mydomain, localhost.\$mydomain, localhost"
}
step_5_info() { echo "$mtaName enable submission service"; }
step_5() {
echoseq -e " [I] Copy following lines...\n"
exe cat "$mtaConfSubmission"
exe read -rep $'\nPress Enter to open the '$mtaConfLoc'/master.cf'
exe vi $mtaConfLoc/master.cf
exe echoseq
exe cat "$mtaConfSmtps"
exe read -rep $'\nPress Enter to open the '$mtaConfLoc'/master.cf'
exe vi $mtaConfLoc/master.cf
}
mtaConfSubmission="$WDIR/$toolName/submissionService"
mtaConfSmtps="$WDIR/$toolName/smtpsService"
step_6_info() { echo "Configure TLS"; }
step_6() {
exe postconf "smtpd_tls_cert_file = /etc/letsencrypt/live/$MAS_DOMAIN/fullchain.pem"
exe postconf "smtpd_tls_key_file = /etc/letsencrypt/live/$MAS_DOMAIN/privkey.pem"
#Force TLSv1.3 or TLSv1.2
exe postconf "smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
exe postconf "smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
exe postconf "smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
exe postconf "smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
echoseq " [I] Restarting $mtaName"
exe service $mtaName restart
}
step_7_info() {
echo "Restrict client access"
echoinfo "Mainly PTR record check"
}
step_7() {
exe postconf -e "smtpd_client_restrictions = permit_mynetworks, reject_unknown_client_hostname"
}
step_8_info() { echo "Install $mdaName"; }
step_8() {
exe apt install $mdaDeps
echoseq -e "\n [I] Installed version: $(dovecot --version)"
}
step_9_info() {
echo "Configure $mdaName"
}
step_9() {
outColor green
cat <<MDA_EOF
# Configuring Mailbox Location
[/etc/dovecot/conf.d/10-mail.conf]
mail_location = maildir:~/Maildir
mail_privileged_group = mail
usermod -aG mail dovecot
# Configuring Authentication Mechanism
[/etc/dovecot/conf.d/10-auth.conf]
disable_plaintext_auth = yes
# Login with full mail address
auth_username_format = %n
# "login" to support older mail clients
auth_mechanisms = plain login
# Configure SSL/TLS Encryption
[/etc/dovecot/conf.d/10-ssl.conf]
ssl = required
ssl_cert = </etc/letsencrypt/live/$MAS_DOMAIN/fullchain.pem
ssl_key = </etc/letsencrypt/live/$MAS_DOMAIN/privkey.pem
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = yes
ssl_dh = </etc/dovecot/dh.pem
openssl dhparam -out /etc/dovecot/dh.pem 4096
# SASL Authentication Between Postfix and Dovecot
[/etc/dovecot/conf.d/10-master.conf]
# Add to service auth {
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0600
user = postfix
group = postfix
}
}
# Auto-subscribe Drafts, Sent, Junk and Trash Folder
and auto delete after 30 days
[/etc/dovecot/conf.d/15-mailboxes.conf]
# Add "auto = create" to folder e.g.:
mailbox Trash {
auto = subscribe
autoexpunge = 30d
special_use = \\Trash
}
# Using Dovecot to Deliver Email to Message Store
Make sure lmtp protocol is installed with dovecot-lmtp
[/etc/dovecot/conf.d/10-master.conf]
# Change lmtp service definition to:
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
postconf -e "mailbox_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "smtputf8_enable = no"
# Clean outgoing mail header from sensitiv information
[/etc/postfix/master.cf]
smtps inet n - y - - smtpd
[...]
-o cleanup_service_name=headclean
#add below "cleanup"
headclean unix n - - - 0 cleanup
-o header_checks=regexp:/etc/postfix/sender_header_checks
[/etc/postfix/sender_header_checks]
/^Received:/ IGNORE
/^X-PHP-Originating-Script:/ IGNORE
/^X-Originating-IP:/ IGNORE
/^X-Mailer:/ IGNORE
/^User-Agent:/ IGNORE
MDA_EOF
}
step_20_info() {
echo "Install postfixadmin and create mysql database"
echoinfo "Virtualize mailboxes, domains and aliases by using a mysql database"
}
step_20_alias() { ALIAS="virtual"; }
step_20() {
local qOpt=
if [ $QUIET -ne 0 ] ; then
qOpt="-q"
fi
exe $WDIR/postfixadmin.sh ${qOpt} install
}
step_21_info() { echo "Create $mtaName mysql query files"; }
step_21() {
# eval needed to expand sourced configuration variables
local localMysqlUser=`eval "echo \"$MAS_VIRTUAL_USER_PART\""`
exe mkdir -p "$mtaMysqlConfLoc"
local mtaFile
local mtaVar
local mtaMysqlFiles=(\
"mysql_virtual_domains_maps"\
"mysql_virtual_mailbox_maps"\
"mysql_virtual_alias_domain_mailbox_maps"\
"mysql_virtual_alias_maps"\
"mysql_virtual_alias_domain_maps"\
"mysql_virtual_alias_domain_catchall_maps"\
)
for mtaFile in ${mtaMysqlFiles[@]}
do
eval 'mtaVar=$MAS_'${mtaFile}
echoseq " [I] creating ${mtaFile}.cf"
exe echo -e "$localMysqlUser\n$mtaVar" > "$mtaMysqlConfLoc/${mtaFile}.cf"
done
exe chown -R root:${mtaUser} "$mtaMysqlConfLoc"
exe chmod 640 "${mtaMysqlConfLoc}"/*
}
step_22_info() { echo "Modify $mtaName configuration for virtual mailboxes"; }
step_22() {
exe postconf -e "virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf"
exe postconf -e "virtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf"
exe postconf -e "virtual_alias_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf"
exe postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
# Apex domain removed, it is handled as virtual domain now
exe postconf -e "mydestination = \$myhostname, localhost.\$mydomain, localhost"
# Base location for the virtual maildirs
exe postconf -e "virtual_mailbox_base = $MAS_VIRTUAL_FOLDER_BASE"
exe postconf -e "virtual_minimum_uid = $MAS_VIRTUAL_USER_ID"
exe postconf -e "virtual_uid_maps = static:$MAS_VIRTUAL_USER_ID"
exe postconf -e "virtual_gid_maps = static:$MAS_VIRTUAL_USER_ID"
}
step_23_info() { echo "Create virtual user $MAS_VIRTUAL_USER and folder $MAS_VIRTUAL_FOLDER_BASE"; }
step_23() {
exe mkdir -p "$MAS_VIRTUAL_FOLDER_BASE"
exe groupadd --gid $MAS_VIRTUAL_USER_ID $MAS_VIRTUAL_USER
exe adduser --disabled-login --disabled-password --home "$MAS_VIRTUAL_FOLDER_BASE" --uid $MAS_VIRTUAL_USER_ID --gid $MAS_VIRTUAL_USER_ID $MAS_VIRTUAL_USER
exe chown -R ${MAS_VIRTUAL_USER}: "$MAS_VIRTUAL_FOLDER_BASE"
exe chmod -R 770 "$MAS_VIRTUAL_FOLDER_BASE"
echoseq " [I] Restarting $mtaName"
exe service $mtaName restart
}
step_24_info() { echo "$mdaName virtualisation configuration instructions"; }
step_24() {
echo "# Configuring Mailbox Location"
echo " [/etc/dovecot/conf.d/10-mail.conf]"
echo " mail_location = maildir:~/Maildir"
echo " mail_home = ${MAS_VIRTUAL_FOLDER_BASE}/%d/%n"
echo
echo "# Configure authentication"
echo " [/etc/dovecot/conf.d/10-auth.conf]"
echo " # Username with domain"
echo " auth_username_format = %u"
echo " # Find and uncomment following line"
echo " !include auth-sql.conf.ext"
echo " # Comment following line to prevent local users from sending mail"
echo " # without having registered an email address"
echo " #!include auth-system.conf.ext"
echo " # Debug login issues in /var/log/maillog by adding:"
echo " auth_debug = yes"
echo " auth_debug_passwords = yes"
echo
echo "# Adding mysql login information"
echo " [/etc/dovecot/dovecot-sql.conf.ext]"
echo " driver = mysql"
echo " connect = host=$MAS_DBHOST dbname=$MAS_DBNAME user=$MAS_DBUSER password='${MAS_DBPASS}'"
echo " default_pass_scheme = MD5"
echo " password_query = SELECT username AS user,password FROM mailbox WHERE username = '%u' AND active='1'"
echo " user_query = SELECT maildir, $MAS_VIRTUAL_USER_ID AS uid, $MAS_VIRTUAL_USER_ID AS gid FROM mailbox WHERE username = '%u' AND active='1'"
echo " iterate_query = SELECT username AS user FROM mailbox"
}
step_25_info() {
echo "Configure sieve for virtual users"
}
step_25() {
echo "# Sieve script configuration"
echo " [$mdaConfDir/90-sieve.conf]"
echo " sieve = file:/var/vmail/%d/%n/sieve;active=/var/vmail/%d/%n/.dovecot.sieve"
echo " sieve_extensions = +notify +imapflags +vnd.dovecot.execute"
echo " sieve_plugins = sieve_extprograms"
echo " sieve_user_log = file:/var/vmail/%d/%n/sieve/sieve.log"
echo
echo "# Enable sieve for lmtp"
echo " [$mdaConfDir/20-lmtp.conf]"
echo " postmaster_address = postmaster@$MAS_DOMAIN"
echo " mail_plugins = $mail_plugins sieve"
echo
echo "# Enable excution of external programs (e.g. to send xmpp messages on certain keywords)"
echo " [$mdaConfDir/90-sieve-extprograms.conf]"
echo " sieve_execute_bin_dir = /usr/lib/dovecot/sieve-execute"
echo
echo "# Notes on execution of scripts"
echo " * Scripts are executed with the $MAS_VIRTUAL_USER user"
echo " * Scripts must no be writeable by others"
echo " (chown root:$MAS_VIRTUAL_USER script; chmod 750 script)"
echo " * \$HOME is set to the virtual users home"
echo " (e.g. /var/vmail/$MAS_DOMAIN/max)"
echo
echo "# Notes about sendxmpp"
echo " * .sendxmpprc resides in every virtual users home"
echo " and must be owned by $MAS_VIRTUAL_USER"
echo " (chown $MAS_VIRTUAL_USER: .sendxmpprc; chmod 700 .sendxmpprc)"
}
step_50_info() { echo "Adding default relay host for sending mails"; }
step_50_alias() { ALIAS="default_relay"; }
step_50() {
if [ ! -f "$saslPassFile" ] ; then
exe postconf -e "relayhost = $MAS_RELAYHOST"
exe postconf -e "smtp_sasl_auth_enable = yes"
exe postconf -e "smtp_sasl_password_maps = hash:$saslPassFile"
addConf -s "$MAS_RELAYHOST $MAS_RELAYUSER:$MAS_RELAYPASS" "$saslPassFile"
fi
echoseq " [I] Updating $saslPassFile"
exe postmap "$saslPassFile"
}
saslPassFile="$mtaConfLoc/sasl_password"
step_52_info() {
echo "Grant access for specific (local) hostnames"
echoinfo "Workaround when local clients connect to 25 with different ips (v6)"
}
step_52_alias() { ALIAS="client_access"; }
step_52() {
if [ ! -f "$mtaClientAccessLoc" ] ; then
echo " [I] Generating $mtaClientAccessLoc"
exep "echo \"# myhost.lan OK\" > \"$mtaClientAccessLoc\""
echo " [I] Don't forget to add the following"
echo " [$mtaConfLoc/main.cf]"
echo " smtpd_relay_restrictions ="
echo " check_client_access hash:$mtaClientAccessLoc"
fi
echoseq " [I] Updating $mtaClientAccessLoc"
exe postmap "$mtaClientAccessLoc"
}
mtaClientAccessLoc="$mtaConfLoc/client_access"
step_54_info() {
echo "Deny recipient access for listed mail addresses"
}
step_54_alias() { ALIAS="recipient_access"; }
step_54() {
if [ ! -f "$mtaRecipientAccessLoc" ] ; then
echoseq " [I] Generating $mtaRecipientAccessLoc"
exep "echo \"# unwanted@${MAS_DOMAIN} 550 No mailbox. Nothing to see here.\" > \"$mtaRecipientAccessLoc\""
echo " [I] Don't forget to add the following"
echo " [$mtaConfLoc/main.cf]"
echo " smtpd_recipient_restrictions ="
echo " check_recipient_access hash:$mtaRecipientAccessLoc"
fi
echoseq " [I] Updating $mtaRecipientAccessLoc"
exe postmap "$mtaRecipientAccessLoc"
}
mtaRecipientAccessLoc="$mtaConfLoc/recipient_access"
step_56_info() { echo "Add sender dependant relay with authentication"; }
step_56_alias() { ALIAS="sender_relay"; }
step_56() {
if [ ! -f "$mtaSenderRelayLoc" ] ; then
echoseq " [I] Generating $mtaSenderRelayLoc"
exep "echo \"# user@extern.com smtp:[mail.extern.com]:587\" > \"$mtaSenderRelayLoc\""
exe postconf -e "smtp_sender_dependent_authentication = yes"
exe postconf -e "sender_dependent_relayhost_maps = hash:$mtaSenderRelayLoc"
exe postconf -e "smtp_sasl_security_options = noanonymous"
exe postconf -e "smtp_sasl_mechanism_filter = plain"
exe postconf -e "smtp_tls_security_level = encrypt"
exe postconf -e "smtp_tls_mandatory_ciphers = high"
echo " [I] Don't forget to add credentials for the new relay"
echo " [$saslPassFile]"
echo " user@extern.com username:passwort"
echo " postmap $saslPassFile"
fi
echoseq " [I] Updating $mtaSenderRelayLoc"
exe postmap "$mtaSenderRelayLoc"
exe postmap "$saslPassFile"
}
mtaSenderRelayLoc="$mtaConfLoc/sender_relay"
step_100_info() {
echo "Send testmail [-u SYSTEMUSER | -f FROM] [TO]"
echoinfo "Send as current user to postmaster@\$MAS_DOMAIN by default"
}
step_100_alias() { ALIAS="test"; }
step_100() {
shift
local arg
local fromAdr
local toAdr="postmaster@$MAS_DOMAIN"
local asUser=
for arg in "$@" ; do
case "$1" in
-f)
shift
fromAdr="-f $1 "
shift
;;
-u)
shift
asUser="sudo -u $1 "
shift
;;
*)
break
;;
esac
done
if [ ! -z $1 ] ; then
toAdr="$1"
fi
exe ${asUser}sh -c "echo \"Subject: Test from Postfix\nIt is \$(date)\n\nGreetings \$(whoami)\" | sendmail ${fromAdr}$toAdr"
}
step_102_info() { echo "Show mail queue"; }
step_102_alias() { ALIAS="showqueue"; }
step_102() {
exe sendmail -bp
}
step_104_info() {
echo "Delete mail queue [ID]"
echoinfo "Delete all queued mails if [ID] is empty"
}
step_104_alias() { ALIAS="delqueue"; }
step_104() {
shift
local msgId="ALL"
if [ ! -z $1 ] ; then
msgId="$1"
fi
exe postsuper -d "$msgId"
}
VERSION_SEQREV=12
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,8 @@
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth

View File

@@ -0,0 +1,9 @@
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_tls_wrappermode=no
-o smtpd_sasl_auth_enable=yes
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth

View File

@@ -0,0 +1,25 @@
#!/bin/bash
MACO_USER="matrix-commander"
MACO_BASE_DIR="/opt/matrix-commander"
MACO_DIR="$MACO_BASE_DIR/matrix-commander"
MACO_SERVICE="[Unit]
Description=Matrix-Commander
After=syslog.target network-online.target
StartLimitIntervalSec=0
[Service]
User=$MACO_USER
Group=$MACO_USER
Type=simple
ExecStart=${MACO_BASE_DIR}/bin/python3 ${MACO_DIR}/matrix-commander.py --listen forever --listen-self
TimeoutStopSec=20
#KillMode=process
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Alias=matrix-commander.service"

144
seqs/matrix-commander.sh Executable file
View File

@@ -0,0 +1,144 @@
#!/bin/bash
toolName=matrix-commander
toolCloneUrl='https://github.com/8go/matrix-commander.git'
toolDeps="python3-pip python3-venv libolm-dev"
toolCredentialDir=
toolEncStoreDir=
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
## or to use sequencer api with global config file:
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return -1
fi
toolCredentialDir="$MACO_BASE_DIR/.config/matrix-commander"
toolEncStoreDir="$MACO_BASE_DIR/.local/share/matrix-commander"
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && APTOPT="-y"
## Return of non zero value will abort the sequence
return 0
}
step_1_info() { echo "Run $toolName"; }
step_1_alias() { ALIAS="run"; }
step_1() {
shift
exe "$MACO_BASE_DIR/bin/python3" "$MACO_DIR/matrix-commander.py" "$@"
}
step_3_info() {
echoinfoArgs "[MESSAGE] [MESSAGE] ..."
echo "Send message"
echoinfo "Each string ([MESSAGE]) is send as separate message"
}
step_3_alias() { ALIAS="message"; }
step_3() {
shift
step run -m "$@"
}
step_50_info() { echo "Install $toolName dependencies"; }
step_50_alias() { ALIAS="install"; }
step_50() {
apt install $toolDeps $APTOPT
}
step_51_info() { echo "Add system user $MACO_USER"; }
step_51() {
id $MACO_USER >/dev/null 2>&1
[ $? -eq 0 ] && endReturn -o 1 "User $MACO_USER already exists"
exe adduser --system $MACO_USER --group --home "${MACO_BASE_DIR}" --no-create-home
}
step_52_info() { echo "Create venv and install $toolName"; }
step_52() {
[ -e "$MACO_BASE_DIR" ] && endReturn -o 1 "$toolName already installed"
exe python3 -m venv "$MACO_BASE_DIR"
endReturn -o $? "Creating virtual environment failed"
exe git clone $toolCloneUrl "$MACO_DIR"
exe chown -R $MACO_USER: "$MACO_BASE_DIR"
exe sudo -u $MACO_USER ${MACO_BASE_DIR}/bin/pip install --upgrade pip
}
step_53_info() { echo "Install python requirements"; }
step_53() {
cat <<NOTES_END
# Remove following packages for headless servers
dbus-python
notify2
NOTES_END
exe read -p "Enter to continue..."
exe "$DEFAULT_EDITOR_SYSTEM" "$MACO_DIR/requirements.txt"
exe sudo -u $MACO_USER ${MACO_BASE_DIR}/bin/pip install -r ${MACO_DIR}/requirements.txt
}
step_55_info() {
echo "Create systemd service for $toolName"
echoinfo "(Make sure to modify the service content in the step configuration)"
}
step_55_alias() { ALIAS="service"; }
step_55() {
local macommanderServiceLoc="/etc/systemd/system/matrix-commander.service"
addConf -s "$MACO_SERVICE" "$macommanderServiceLoc"
exe systemctl daemon-reload
}
step_57_info() { echo "First run to create credential file and encryption store"; }
step_57_alias() { ALIAS="firstrun"; }
step_57() {
exe sudo -u "$MACO_USER" mkdir -p "$toolCredentialDir" "$toolEncStoreDir"
exe cd "$toolCredentialDir"
step run
[ -e ./store ] && exe mv store "$toolEncStoreDir"
echoseq " [I] use \"$SEQ_NAME run --verify\" to verify against an existing session (like Element)"
}
step_60_alias() { ALIAS="notes"; }
step_60() {
outColor green
cat <<NOTES_EOF
# Verify matrix-commander "device"
For emoji verification to work, the matrix-commander user needs to be at least in one room.
Enter the room on Element and goto
* Room Info -> People -> select matrix commander user -> Security -> sessions -> matrix-commander session
* verify with emojis
## Credential information location
matrix-commander expects the following files to be in place for the user to be able to
send/receive messages
credentials.json - $MACO_BASE_DIR/.config/matrix-commander/credentials.json
store - $MACO_BASE_DIR/.local/share/matrix-commander/store
NOTES_EOF
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,3 @@
#!/bin/bash
SEQ_DIMENSION_DIR="/opt/matrix-dimension"

79
seqs/matrix-dimension.sh Executable file
View File

@@ -0,0 +1,79 @@
#!/bin/bash
toolName=matrix-dimension
toolDownUrl="https://github.com/turt2live/matrix-dimension.git"
toolAptDeps="nodejs"
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
## or to use sequencer api with global config file:
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return -1
fi
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && APTOPT="-y"
echoerr " [W] $SCRIPT_NAME is still in alpha stage"
echoerr " TODO: - systemd script"
echoerr " - initial config creation"
## Return of non zero value will abort the sequence
return 0
}
step_1_info() { echo "Install $toolName dependencies"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exep curl -sL https://deb.nodesource.com/setup_12.x \| bash -
exe apt install $toolAptDeps $APTOPT
}
step_2_info() { echo "Setup and build"; }
step_2_alias() { ALIAS="setup"; }
step_2() {
if [ ! -e "$SEQ_DIMENSION_DIR" ]; then
exe mkdir -p "$SEQ_DIMENSION_DIR"
exe cd "$SEQ_DIMENSION_DIR/.."
# Download dimension
exe git clone $toolDownUrl
fi
exe cd "$SEQ_DIMENSION_DIR"
# Install dependencies
exe npm install
# Build it
exe npm run build
}
step_10_info() { echo "Start $toolName"; }
step_10_alias() { ALIAS="start"; }
step_10() {
if [ ! -e "$SEQ_DIMENSION_DIR" ]; then
echoerr " [E] $toolName not found ad $SEQ_DIMENSION_DIR"
return 1;
fi
exe cd "$SEQ_DIMENSION_DIR"
# TODO is "node build/app/index.js" enough after build
# NODE_ENV=production npm run start:app runs actually:
# start:app: `npm run-script build && node build/app/index.js`
exep NODE_ENV=production node build/app/index.js
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh

8
seqs/matrix.cfg.example Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
# Location of synapse virtual environment
MATRIX_HOME="/opt/synapse"
# Corresponds to "server_name" in synapse config
MATRIX_DOMAIN="matrix.example.com"
# Provide an admin access token for API calls
MATRIX_ACCESS=""

563
seqs/matrix.sh Executable file
View File

@@ -0,0 +1,563 @@
#!/bin/bash
toolName=synapse
toolDeps="build-essential python3-dev libffi-dev python3-pip python3-setuptools postgresql libssl-dev virtualenv libjpeg-dev libxslt1-dev libpq5 libpq-dev"
toolDeps+=" jq" # used as helper for api access
toolDepsRaspi="libopenjp2-7 libtiff5"
toolUser="synapse"
toolGroup="synapse"
toolServiceName="matrix-synapse"
synapseHashTool="env/bin/hash_password"
toolUrlLocal="http://localhost:8008"
# Filled by configuration
toolConfig=
toolUrl=
# Needed for different steps
postgresDb=""
postgresUser=""
postgresPass=""
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="matrix.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
if [ "$(which lsb_release)" == "" ] ; then
echoerr " [W] Cannot detect OS. Assuming Raspberry Pi OS"
osName="Raspbian"
else
osName=$(lsb_release -is)
distName=$(lsb_release -cs)
fi
if [ "$osName" == "" ] ; then
echoerr " [W] Error dedecting OS. Assuming Raspberry Pi OS"
osName="Raspbian"
fi
echo " [I] Detected OS: $osName $distName"
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
toolConfig="${MATRIX_HOME}/homeserver.yaml"
toolUrl="https://$MATRIX_DOMAIN"
localHome="$MATRIX_HOME"
echo " $toolName home: $MATRIX_HOME"
echo " $toolName domain: $MATRIX_DOMAIN"
fi
return 0
}
step_1_info() { echo "Installing $toolName dependencies"; }
step_1_alias() { ALIAS="install"; }
step_1() {
local aptOption=
exe apt update
endReturn -o $? "Updating apt repositories failed"
if [ $QUIET -ne 0 ] ; then
aptOption="-y"
else
aptOption=""
fi
if [ "$osName" != "Raspbian" ] ; then
toolDepsRaspi=""
fi
exe apt install $toolDeps $toolDepsRaspi $aptOption
}
step_2_info() { echo "Create postgres database for $toolName"; }
step_2_alias() { ALIAS="createdb"; }
step_2() {
readDatabaseInfos
exe cd ~postgres
exe su -c "psql -c \"CREATE USER ${postgresUser} WITH ENCRYPTED password '${postgresPass}';\"" - postgres
exe su -c "psql -c \"CREATE DATABASE ${postgresDb} ENCODING \"UTF8\" LC_COLLATE='C' LC_CTYPE='C' template=template0 OWNER ${postgresUser};\"" - postgres
exe su -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE \"${postgresDb}\" to ${postgresUser};\"" - postgres
}
step_3_info() { echo "Create $toolName user and group"; }
step_3() {
exe addgroup "$toolGroup"
exe adduser --system --home ${MATRIX_HOME}/ --no-create-home --disabled-password --shell /bin/nologin --ingroup "$toolGroup" "$toolUser"
}
step_4_info() { echo "Install $toolName"; }
step_4_alias() { ALIAS="virtualenv"; }
step_4() {
exe mkdir -p "$MATRIX_HOME"
exe virtualenv -p python3 "${MATRIX_HOME}/env"
exe cd "$MATRIX_HOME"
exe source "${MATRIX_HOME}/env/bin/activate"
exe pip install --upgrade pip
exe pip install --upgrade setuptools
exe pip install matrix-synapse[postgres] lxml
}
step_5_info() { echo "Create default configuration and folder structure"; }
step_5_alias() { ALIAS="defaultconfig"; }
step_5() {
# Create default configuration
exe python3 -m synapse.app.homeserver --server-name "$MATRIX_DOMAIN" --config-path homeserver.yaml --generate-config --report-stats=no
exe deactivate
# Create media directories
exe mkdir -p ${MATRIX_HOME}/media_store ${MATRIX_HOME}/uploads
exe chmod 770 "${MATRIX_HOME}/media_store" "${MATRIX_HOME}/uploads"
# Allow matrix to write its logs in /opt/synapse
exe chmod 755 "${MATRIX_HOME}"
exe chown ${toolUser}:${toolGroup} "${MATRIX_HOME}" "${MATRIX_HOME}/media_store" "${MATRIX_HOME}/uploads"
}
step_6_info() { echo "Open $toolName configuration file"; }
step_6() {
exe vi "$toolConfig"
}
step_7_info() { echo "Create $toolName systemd service"; }
step_7_alias() { ALIAS="systemd"; }
step_7() {
# eval needed to expand sourced configuration variables
local localService=`eval "echo \"$toolService\""`
addConf -c "$localService" "$toolServiceLoc"
exe systemctl daemon-reload
exe systemctl enable ${toolServiceName}.service
exe service ${toolServiceName} start
}
toolServiceLoc="/etc/systemd/system/${toolServiceName}.service"
toolService="[Unit]
Description=Matrix Synapse service
After=network.target postgresql.service
[Service]
Type=forking
WorkingDirectory=\${MATRIX_HOME}/
ExecStart=\${MATRIX_HOME}/env/bin/synctl start
ExecStop=\${MATRIX_HOME}/env/bin/synctl stop
ExecReload=\${MATRIX_HOME}/env/bin/synctl restart
User=\${toolUser}
Group=\${toolGroup}
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=synapse
[Install]
WantedBy=multi-user.target"
step_10_info() {
echo -n "Upgrade $toolName installation"
if [ $CONTEXT_HELP -eq 0 ] ; then
echo " at $MATRIX_HOME"
else
echo
fi
}
step_10_alias() { ALIAS="upgrade"; }
step_10() {
echo " [I] Upgrading $toolName"
exe source "${MATRIX_HOME}/env/bin/activate"
exe pip install --upgrade pip
exe pip install --upgrade matrix-synapse
saveReturn $?
exe deactivate
endReturn "Error upgrading $toolName"
echo " [I] Restarting $toolName"
step restart
echo " [I] New Version:"
exe sleep 2
step version
}
step_12_info() { echo "Restart $toolName systemd service"; echo; }
step_12_alias() { ALIAS="restart"; }
step_12() {
exe service ${toolServiceName} restart
}
step_14_info() {
echoinfoArgs "[IP]:8008"
echo "Show $toolName version"
}
step_14_alias() { ALIAS="version"; }
step_14() {
local synapseIP=localhost
shift
if [ ! -z $1 ]; then
synapseIP="$1"
fi
local apiCall="http://${synapseIP}:8008/_synapse/admin/v1/server_version"
# -sS to suppress download progress of curl
exep "curl -sS \"$apiCall\" | python -m json.tool | grep _version"
}
step_16_info() {
echoinfoArgs "[OPTION] [IP]:8008"
echo "List all registered users"
echoinfo "[OPTION]"
echoinfo " -r : Raw json output"
}
step_16_alias() { ALIAS="listuser"; }
step_16() {
adminTokenCheck
endReturn -o $? "Admin token needed. Check $SEQ_CONFIG_FILE"
shift
local synapseIP=localhost
local grepOut=" | grep -E '(\"total\":|\"name\":)'"
for arg in "$@" ; do
case "$1" in
-r)
grepOut=""
shift
;;
*)
break
;;
esac
done
if [ ! -z $1 ]; then
synapseIP="$1"
fi
local apiCall="http://${synapseIP}:8008/_synapse/admin/v2/users"
exep "curl -sS --header \"Authorization: Bearer $MATRIX_ACCESS\" \"$apiCall\" | python -m json.tool $grepOut"
}
step_18_info() { echo "Create new user"; }
step_18_alias() { ALIAS="adduser"; }
step_18() {
exe /opt/synapse/env/bin/register_new_matrix_user -c "$MATRIX_HOME/homeserver.yaml" $toolUrlLocal
}
step_20_info() {
shift
echoinfoArgs "[USER NAME]"
echo -n "Reset user password"
[ $CONTEXT_EXE -ne 0 ] && echoinfo " for $1" || echo
}
step_20_alias() { ALIAS="resetpw"; }
step_20() {
shift
local user=
if [ ! -z $1 ]; then
user="$1"
else
exe read -p "User name: " user
fi
if [ -z $user ]; then
echoerr "No user name provided"
return 1
fi
local pw="$("${MATRIX_HOME}/${synapseHashTool}")"
# Escaping twice because password contains $ which would be treated as variables
local string="\"UPDATE users SET password_hash=\''${pw}'\' WHERE name=\''@${user}:${MATRIX_DOMAIN}'\'\""
exep "echo \"$string\" | su postgres -c 'psql -d synapse -f -'"
}
step_22_info() {
echoinfoArgs "[OPTION] [IP]:8008"
echo "List all rooms"
echoinfo "[OPTION]"
echoinfo " -r : Raw json output"
}
step_22_alias() { ALIAS="listrooms"; }
step_22() {
adminTokenCheck
endReturn -o $? "Admin token needed. Check $SEQ_CONFIG_FILE"
shift
local arg
local synapseIP=localhost
local grepOut=" | grep -E '(\"total\":|\"name\":|\"room_id\":)'"
for arg in "$@" ; do
case "$1" in
-r)
grepOut=""
shift
;;
*)
break
;;
esac
done
if [ ! -z $1 ]; then
synapseIP="$1"
fi
local apiCall="http://${synapseIP}:8008/_synapse/admin/v1/rooms"
exep "curl -sS --header \"Authorization: Bearer $MATRIX_ACCESS\" \"$apiCall\" | python -m json.tool $grepOut"
}
step_24_info() {
echoinfoArgs "[OPTION] [ROOM ID] [IP]:8008"
echo "List all room members"
echoinfo "[OPTION]"
echoinfo " -r : Raw json output"
}
step_24_alias() { ALIAS="listmember"; }
step_24() {
adminTokenCheck
endReturn -o $? "Admin token needed. Check $SEQ_CONFIG_FILE"
shift
local roomId=""
local synapseIP=localhost
local grepOut=" | grep -E '(\"total\":|\"members\":|\"@)'"
for arg in "$@" ; do
case "$1" in
-r)
grepOut=""
shift
;;
*)
break
;;
esac
done
if [ ! -z $1 ]; then
roomId="$1"
shift
fi
if [ ! -z $1 ]; then
synapseIP="$1"
fi
local apiCall="http://${synapseIP}:8008/_synapse/admin/v1/rooms/$roomId/members"
exep "curl -sS --header \"Authorization: Bearer $MATRIX_ACCESS\" \"$apiCall\" | python -m json.tool $grepOut"
}
step_26_info() {
echoinfoArgs "[IP]:8008"
echo "Delete rooms without local users"
echoinfo " [IP] : default is localhost"
}
step_26_alias() { ALIAS="purge"; }
step_26() {
adminTokenCheck
endReturn -o $? "Admin token needed. Check $SEQ_CONFIG_FILE"
shift
local i
local arg
local synapseIP=localhost
if [ ! -z $1 ]; then
synapseIP="$1"
fi
local apiCall="http://${synapseIP}:8008/_synapse/admin/v1/rooms"
local arrRoom=( $(curl -sS --header "Authorization: Bearer $MATRIX_ACCESS" "$apiCall" | jq '.rooms[] | select(.joined_local_members == 0) | .room_id') )
for i in "${!arrRoom[@]}" ; do
arrRoom[$i]="${arrRoom[$i]:1:${#arrRoom[$i]}-2}"
done
for i in "${arrRoom[@]}" ; do
step deleteroom "$i"
done
}
step_28_info() {
echoinfoArgs "<ROOM ID> [IP]:8008"
echo "Delete room"
}
step_28_alias() { ALIAS="deleteroom"; }
step_28() {
adminTokenCheck
endReturn -o $? "Admin token needed. Check $SEQ_CONFIG_FILE"
shift
local roomId=""
local synapseIP=localhost
if [ ! -z $1 ]; then
roomId="$1"
shift
else
endReturn -o 1 "No room ID specified"
fi
if [ ! -z $1 ]; then
synapseIP="$1"
fi
echo " [I] Deleting room with ID: $roomId"
local apiCall="http://${synapseIP}:8008/_synapse/admin/v2/rooms/$roomId"
exep "curl -sS --header \"Authorization: Bearer $MATRIX_ACCESS\" \
-X DELETE \
-H \"Content-Type: application/json\" -d \"{}\" \
\"$apiCall\" | python -m json.tool"
#end
}
# As note for further improvement
# See https://github.com/matrix-org/synapse/blob/develop/docs/admin_api/rooms.md#delete-room-api
postDataDeleteRoom()
{
cat <<EOF
{
"new_room_user_id": "@someuser:example.com",
"room_name": "Content Violation Notification",
"message": "Bad Room has been shutdown due to content violations on this server. Please review our Terms of Service.",
"block": true,
"purge": true
}
EOF
}
step_30_info() { echoinfoArgs "[DATABASE]"; echo "Debloat postgres"; echo; }
step_30_alias() { ALIAS="debloat"; }
step_30() {
shift
local pgVerboseReId=" (VERBOSE) "
local pgVerboseVac=" VERBOSE"
if [ $VERBOSE == 0 ]; then
pgVerboseReId=" "
pgVerboseVac=""
fi
if [ -z $1 ]; then
readDatabaseInfos
else
postgresDb="$1"
fi
echo " [I] Stopping ${toolServiceName}"
exe service ${toolServiceName} stop
endReturn -o $? "Couldn't stop ${toolServiceName}. Stopping debloat."
exe cd ~postgres
exe su -c "psql -d ${postgresDb} -c \"REINDEX${pgVerboseReId}DATABASE ${postgresDb};\"" - postgres
exe su -c "psql -c \"VACUUM FULL${pgVerboseVac};\"" - postgres
echo -e "\n [I] Starting ${toolServiceName}"
exe service ${toolServiceName} start
}
step_50_info() { echo "Drop postgres database for $toolName"; }
step_50_alias() { ALIAS="dropdb"; }
step_50() {
readDatabaseInfos
exe cd ~postgres
exe su -c "psql -c \"DROP DATABASE ${postgresDb};\"" - postgres
}
step_52_info() { echo "Backup postgres database"; }
step_52_alias() { ALIAS="backupdb"; }
step_52() {
local DELYEAR=$(($(date +%Y)-2))
if [ ! -s ~/.pgpass ] ; then
echo " [I] For unattended backup please define ~/.pgpass containing credentials"
echo " e.g. localhost:5432:database:user:pass"
echo "Backup custom pg format with standard user / database: synapse / synapse"
fi
exep "pg_dump -h 127.0.0.1 -U synapse -Fc synapse | bzip2 -c > ${toolDbBackupFolder}/`date +%Y-%m-%d\"_\"%H-%M-%S`.backup.bz2"
exe rm -f ${toolDbBackupFolder}/${DELYEAR}*
}
toolDbBackupFolder=/root/backupdb
step_54_info() { echo "Postgres database restore"; }
step_54_alias() { ALIAS="restoredb"; }
step_54() {
echo " [I] Postgres database restore procedure"
echo "1. Create a empty postgres database first (step 4)"
echo "2. psql -h <host> -U <database user> -d <database name> -W -f <sql dump file>"
echo " e.g. psql -h 127.0.0.1 -U synapse -d synapse -W -f 2018-06-07_18-10-56.sql"
echo "or"
echo "3. Custom postgres format dump restore:"
echo " pg_restore -h localhost -p 5432 -U synapse -d new_db -v \"10.70.0.61.backup\""
echo
echo "Available postgresql databases:"
exe cd ~postgres
exe su postgres -c "psql -c '\l'"
echo "Available postgresql user:"
exe su postgres -c "psql -c '\du'"
}
step_56_info() { echo "$toolName migration notes"; }
step_56_alias() { ALIAS="migrate"; }
step_56() {
echo " [I] Backup database"
echo " ./postgres.sh backupdb synapse"
echo
echo " [I] Backup virtual env folders except \"env\""
echo " cd ${MATRIX_HOME}"
echo " tar czf ../\`date +%Y-%m-%d\"_\"%H-%M-%S\`.synapse_bu.tar.gz --exclude=\"./env\" ."
echo
echo " [I] Transfer both backup files to target server"
echo
echo " [I] Install $toolName on the target server up to step \"virtualenv\""
echo " (Stop after first run and edit $SEQ_CONFIG_FILE)"
echo " ./matrix.sh install"
echo " cd ${MATRIX_HOME}"
echo " tar xf ...synapse_bu.tar.gz"
echo " Follow the instructions of:"
echo " ./matrix.sh restoredb"
echo " ./matrix.sh systemd"
echo
echo " [I] $toolName should be running. Now modify the reverse proxy configuration"
}
# Read postgres database information dbname/user/pass if empty
readDatabaseInfos() {
if [ "$postgresDb" == "" ] ; then
read -p "Enter postgres database name: " postgresDb
endCheckEmpty postgresDb "database"
fi
if [ "$postgresUser" == "" ] ; then
read -p "Enter postgres user name: " postgresUser
endCheckEmpty postgresUser "user name"
fi
if [ "$postgresPass" == "" ] ; then
read -s -p "Enter postgres password: " postgresPass
endCheckEmpty postgresPass "password"
fi
echo
}
# Needs readDatabaseInfos() to execute some commands
toolScript() {
if [ ! -z "$1" ] ; then
readDatabaseInfos
fi
}
# End step if no admin access token is configured
adminTokenCheck() {
if [ -z "$MATRIX_ACCESS" ] ; then
[ $QUIET -eq 0 ] && read -s -p "Please enter admin access tocken: " MATRIX_ACCESS
# return 1 if it is still empty
[ -z "$MATRIX_ACCESS" ] && return 1
fi
return 0
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh

199
seqs/matterbridge.sh Executable file
View File

@@ -0,0 +1,199 @@
#!/bin/bash
#
## Installation of chat bridge matterbridge
toolName="matterbridge"
repoName="42wim"
toolLatestUrl="https://api.github.com/repos/${repoName}/${toolName}/releases/latest"
toolVersion=$(curl --silent "$toolLatestUrl" | grep -Po '"tag_name": "v\K.*?(?=")')
toolDownload="https://github.com/${repoName}/${toolName}/releases/download/v${toolVersion}/${toolName}-${toolVersion}-linux-armv6"
toolDir="/usr/local/bin"
toolLoc="${toolDir}/${toolName}"
toolWdir="/opt/${toolName}"
toolConfig="${toolName}.toml"
toolConfigLoc="${toolWdir}/${toolConfig}"
toolService="[Unit]
Description=${toolName}
After=network.target matrix-synapse.service
[Service]
Type=simple
ExecStart=${toolLoc} -conf ${toolWdir}/matterbridge.toml
Restart=always
RestartSec=30
WorkingDirectory=${toolWdir}
User=root
Group=root
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=${toolName}
[Install]
WantedBy=multi-user.target"
toolServiceLoc="/etc/systemd/system/${toolName}.service"
readonly goDir="/usr/local/go"
readonly goDownLoc="/tmp/go.tar.gz"
step_config() {
if [ -z $toolVersion ] ; then
echoerr " [E] Couldn't determine latest version of $toolName"
fi
}
step_1_info() {
echo "Downloading $toolName version ${toolVersion} to ${toolLoc} from:"
echoinfo "$toolDownload"
}
step_1_alias() { ALIAS="install"; }
step_1() {
step upgrade
endReturn -o $? "Download failed"
}
step_2_info() { echo "Create required directory structure"; }
step_2() {
exe mkdir -p ${toolWdir}
exe touch ${toolConfigLoc}
exe chmod -R 700 ${toolWdir}
exe chmod +x ${toolLoc}
}
step_3_info() { echo "Creating systemd service"; }
step_3() {
addConf -s "$toolService" "$toolServiceLoc"
endReturn -o $? "Creating service failed"
}
step_4_info() { echo "Enable $toolName service"; }
step_4() {
exe systemctl enable ${toolName}
echo " [I] Before proceeding to run ${toolName} you need to modify ${toolConfigLoc} first"
echo
}
step_5_info() { echo "Show configuration notes"; }
step_5_alias() { ALIAS="notes"; }
step_5() {
outColor green
cat <<NOTES_END
# Sample configuration
https://raw.githubusercontent.com/${repoName}/${toolName}/v${toolVersion}/matterbridge.toml.simple"
NOTES_END
}
step_10_info() { echo "Backup existing executable"; }
step_10_alias() { ALIAS="backup"; }
step_10() {
if [ -f "$toolLoc" ] ; then
local toolBackup=
if [ ! -z ${versionNow} ] ; then
toolBackup="${toolDir}/${toolName}_${versionNow}"
else
toolBackup="${toolDir}/${toolName}_bu"
fi
exe service ${toolName} stop >>/dev/null 2>&1
echoseq -n " [I] Backing up existing executable to ${toolBackup}..."
exe cp -ar "$toolLoc" "$toolBackup" && echoseq "ok"
fi
}
versionNow=$([ ! -z $(which ${toolName}) ] && ${toolName} --version | sed 's/.*version: \([0-9.]\+\).*/\1/')
step_12_info() {
if [ ! -z $versionNow ] ; then
if [ "$toolVersion" == "$versionNow" ] ; then
echo "No upgrade available. Already on latest: $versionNow"
else
echo "Download new version $toolVersion to $toolDir"
echoinfo " - installed version: $versionNow -"
fi
else
echo "Download new version $toolVersion to $toolDir"
fi
echo
}
step_12_alias() { ALIAS="upgrade"; }
step_12() {
step backup
exe wget -O "$toolLoc" $toolDownload
endReturn -o $? "Download failed"
exe chmod +x "$toolLoc"
exe service ${toolName} restart >>/dev/null 2>&1
return 0
}
step_30_info() {
echoinfoArgs "[OPTIONS]"
echo "Download go"
echoinfo " [OPTIONS]"
echoinfo " --arch, -a : armhf(default), arm64"
echoinfo " CPU architecture for downloading go sources"
}
step_30_alias() { ALIAS="build"; }
step_30() {
shift
local goVer="$(curl --silent -L https://go.dev/dl | \
grep --max-count 1 -E "go[[:digit:]\.]{3,}.*\.tar\.gz" |\
sed 's/.*\/\(go.*\)\.linux.*/\1/g')"
local goArch="armhf" #arm64"
case "${1}" in
--arch|-a)
goArch="${2}"
shift 2 ;;
esac
[[ "${goArch}" == "armhf" ]] && goArch="armv6l"
local goDownUrl="https://go.dev/dl/${goVer}.linux-${goArch}.tar.gz"
# Download latest go
if [ ! -e "${goDir}" ] ; then
echoseq "Download go${goVer}: ${goDownUrl}"
exe wget -O "${goDownLoc}" ${goDownUrl}
endReturn -o $? "Download ${goVer} failed"
exe tar -C "$(dirname -- "${goDir}")" -xzf "${goDownLoc}"
endReturn -o $? "Extraction ${goVer} failed"
fi
}
step_31_info() { echo "Compile matterbridge"; }
step_31() {
local mabrTags="\
noapi,\
nodiscord,\
nogitter,\
noharmony,\
noirc,\
nokeybase,\
nomattermost,\
nomsteams,\
norocketchat,\
nonctalk,\
nomumble,\
noslack,\
nosshchat,\
notelegram,\
notwitch,\
novk,\
nozulip,\
whatsappmulti"
# Compile matterbridge
exe "${goDir}/bin/go" install -tags ${mabrTags} github.com/42wim/matterbridge@master
step backup
exe cp -ar "${HOME}/go/bin/matterbridge" "${toolDir}"
}
step_32_info() { echo "Clean temporary files"; }
step_32() {
exe rm -f "${goDownLoc}"
}
# Sequence Revision
VERSION_SEQREV=15
# Path to sequencer
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,5 @@
#!/bin/bash
MAYAN_DB=
MAYAN_DBUSER=
MAYAN_DBPASS=

237
seqs/mayan-edms.sh Executable file
View File

@@ -0,0 +1,237 @@
#!/bin/bash
toolName="Mayan EDMS"
toolVersion="4.2.1"
toolRoot="/opt/mayan-edms"
toolMediaFolder="/opt/mayan-edms/media"
# Needed for different steps
postgresDb=""
postgresUser=""
postgresPass=""
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
## or to use sequencer api with global config file:
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
postgresDb="$MAYAN_DB"
postgresUser="$MAYAN_DBUSER"
postgresPass="$MAYAN_DBPASS"
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return -1
fi
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && APTOPT="-y"
## Return of non zero value will abort the sequence
return 0
}
step_1_info() { echo "Install libreoffice without gui"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
exe apt --no-install-recommends install libreoffice -y
}
step_2_info() { echo "Get $toolName binary dependencies"; }
step_2() {
exe apt-get install libimage-exiftool-perl g++ gcc coreutils ghostscript gnupg1 \
graphviz libfuse2 libjpeg-dev libmagic1 libpq-dev libpng-dev libtiff-dev libldap2-dev libsasl2-dev \
poppler-utils postgresql python3-dev python3-pip python3-venv python3-virtualenv \
redis-server sane-utils supervisor tesseract-ocr tesseract-ocr-deu zlib1g-dev -y
endReturn -o $? "Binary dependencies installation failed"
exe systemctl enable supervisor
exe systemctl stop supervisor
}
step_3_info() { echo "Create virtual environment"; }
step_3() {
exe adduser --disabled-password --disabled-login --no-create-home --gecos "" mayan
exe usermod -a -G users mayan
exe python3 -m venv ${toolRoot}
endReturn -o $? "Creating virtual environment failed"
exe chown -R mayan:mayan ${toolRoot}
}
step_4_info() { echo "Create postgres database for $toolName"; }
step_4_alias() { ALIAS="createdb"; }
step_4() {
readDatabaseInfos
exe cd ~postgres
exe sudo -u postgres psql -c "CREATE USER ${postgresUser} WITH password '${postgresPass}';"
# -O owner : Specifies the database user who will own the new database.
exe sudo -u postgres createdb -O ${postgresUser} ${postgresDb}
}
step_5_info() { echo "Install $toolName"; }
step_5() {
# upgrade pip first
step upgradepip
exe sudo -u mayan ${toolRoot}/bin/pip install --no-cache-dir mayan-edms==$toolVersion
endReturn -o $? "pip install for $toolName failed"
exe sudo -u mayan ${toolRoot}/bin/pip install --no-cache-dir psycopg2==2.8.4 redis==3.4.1
endReturn -o $?
}
step_6_info() { echo "Supervisord configuration for $toolName"; }
step_6_alias() { ALIAS="supervisorconf"; }
step_6() {
addConf -c "" "$supervisordConfLoc"
toolScript "platformtemplate supervisord > ${supervisordConfLoc}"
}
supervisordConfLoc="/etc/supervisor/conf.d/mayan.conf"
step_7_info() { echo "Redis configuration file"; }
step_7() {
addConf -a "$redisConf" "$redisConfLoc"
exe systemctl restart redis
}
step_8_info() { echo "Initial setup $toolName and start supervisor"; }
step_8() {
toolScript initialsetup
#exe sudo -u mayan MAYAN_MEDIA_ROOT=${toolMediaFolder} ${toolRoot}/bin/mayan-edms.py collectstatic --noinput # only < 3.4
exe systemctl start supervisor
}
redisConfLoc="/etc/redis/redis.conf"
redisConf="\
maxmemory-policy allkeys-lru
save \"\"
databases 2"
step_10_info() {
echoinfoArgs "[OPTIONS]"
echo "Upgrade $toolName to $toolVersion"
echoinfo " [OPTIONS]"
echoinfo " super : update also supervisor configuration"
echoinfo " (manual redis password update may be needed)"
}
step_10_alias() { ALIAS="upgrade"; }
step_10() {
shift # don't need the step number
step upgradepip
exe curl -o "$uninstallRemovalsLoc" https://gitlab.com/mayan-edms/mayan-edms/raw/master/removals.txt
exe sudo -u mayan ${toolRoot}/bin/pip uninstall -r "$uninstallRemovalsLoc"
endReturn -o $?
exe systemctl stop supervisor
exe sudo -u mayan ${toolRoot}/bin/pip install --no-cache-dir mayan-edms==$toolVersion
endReturn -o $?
toolScript performupgrade
#toolScript preparestatic --noinput # only < 3.4
case $1 in
"super")
# Generating new supervisor file
step supervisorconf ;;
esac
exe systemctl start supervisor
}
uninstallRemovalsLoc="/tmp/removals.txt"
step_13_info() { echo "$toolName management script"; }
step_13_alias() { ALIAS="manage"; }
step_13() {
shift
if [ -z "$1" ] || [ "$1" == "" ] ; then
echo -n "Command (empty for help): "
if [ $DRY != 0 ]; then
echo " dryrun"
else
read command
fi
else
command="$@"
fi
toolScript "$command"
}
step_15_info() { echo "Upgrade python pip"; }
step_15_alias() { ALIAS="upgradepip"; }
step_15()
{
exe ${toolRoot}/bin/pip install --upgrade pip
}
step_20_info() { echo "Backup postgres database to media folder"; }
step_20_alias() { ALIAS="backupdb"; }
step_20() {
local DELYEAR=$(($(date +%Y)-2))
if [ ! -s ~/.pgpass ] ; then
echo " [I] For unattended backup please define ~/.pgpass containing credentials for user mayan"
echo " e.g. localhost:5432:mayan:mayan:pass4mayan"
echo "Backup custom pg format with standard user / database: mayan / mayan"
fi
exep "pg_dump -h 127.0.0.1 -U mayan -Fc mayan | bzip2 -c > ${toolDbBackupFolder}/`date +%Y-%m-%d\"_\"%H-%M-%S`.backup.bz2"
exe rm -f ${toolDbBackupFolder}/${DELYEAR}*
}
toolDbBackupFolder=${toolMediaFolder}/backupdb
step_22_info() { echo "Postgres database restore"; }
step_22_alias() { ALIAS="restoredb"; }
step_22() {
echo " [I] Postgres database restore procedure"
echo "1. Create a empty postgres database first (step 4)"
echo "2. psql -h <host> -U <database user> -d <database name> -W -f <sql dump file>"
echo " e.g. psql -h 127.0.0.1 -U mayan -d mayan -W -f 2018-06-07_18-10-56.sql"
echo "or"
echo "3. Custom postgres format dump restore:"
echo " pg_restore -h localhost -p 5432 -U mayan -d new_db -v \"10.70.0.61.backup\""
echo
echo "Available postgresql databases:"
exe cd ~postgres && sudo -u postgres psql -c '\l'
echo "Available postgresql user:"
exe cd ~postgres && sudo -u postgres psql -c '\du'
}
# Read postgres database information dbname/user/pass if empty
readDatabaseInfos() {
if [ -z "$postgresDb" ] ; then
read -p "Enter postgres database name: " postgresDb
endCheckEmpty postgresDb "database"
fi
if [ -z "$postgresUser" ] ; then
read -p "Enter postgres user name: " postgresUser
endCheckEmpty postgresUser "user name"
fi
if [ -z "$postgresPass" ] ; then
read -s -p "Enter postgres password: " postgresPass
endCheckEmpty postgresPass "password"
fi
echoseq
}
# Needs readDatabaseInfos() to execute some commands
toolScript() {
if [ ! -z "$1" ] ; then
readDatabaseInfos
fi
exep "sudo -u mayan \
MAYAN_DATABASES=\"{'default':{'ENGINE':'django.db.backends.postgresql','NAME':'${postgresDb}','PASSWORD':'${postgresPass}','USER':'${postgresUser}','HOST':'127.0.0.1'}}\" \
MAYAN_MEDIA_ROOT=${toolMediaFolder} \
${toolRoot}/bin/mayan-edms.py $*"
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh

150
seqs/motioneye.sh Executable file
View File

@@ -0,0 +1,150 @@
#!/bin/bash
toolName=motioneye
# Supporting tools dependencies (ffmpeg and motion)
toolDeps="ffmpeg libmariadb3 libpq5 libmicrohttpd12"
# Motioneye dependencies
toolDeps+=" python-pip python-dev libssl-dev libcurl4-openssl-dev libjpeg-dev libz-dev"
toolCfgDir="/etc/motioneye"
SEQ_OSNAME=
SEQ_DISTNAME=
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
#CONFIG_FILE_NAME="${toolName}.cfg"
#CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
## e.g. to source a config file manually:
#. "$CONFIG_FILE"
## or to use sequencer api:
#initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
#if [ $? -eq 0 ] ; then
# CONFIG=1
#fi
if [ "$(which lsb_release)" == "" ] ; then
echoerr " [W] Cannot detect OS. Assuming Ubuntu"
SEQ_OSNAME="Ubuntu"
else
SEQ_OSNAME=$(lsb_release -is)
SEQ_DISTNAME=$(lsb_release -cs)
fi
if [ "$SEQ_OSNAME" == "" ] ; then
echoerr " [W] Error dedecting OS. Assuming Ubuntu"
SEQ_OSNAME="Ubuntu"
fi
echo " [I] Detected OS: $SEQ_OSNAME $SEQ_DISTNAME"
}
step_1_info() { echo "Install $toolName dependencies"; }
step_1_alias() { ALIAS="install"; }
step_1() {
local aptOption=
local pyVersion=$(python -V 2>&1)
if [[ ! "$pyVersion" =~ \ 2\.[7-9]+ ]] ; then
echoerr " [E] Motioneye requires python version 2.7 but $pyVersion was found."
return 1
fi
exe apt update
endReturn -o $? "Updating apt repositories failed"
if [ $QUIET -ne 0 ] ; then
aptOption="-y"
else
aptOption=""
fi
exe apt install $toolDeps $aptOption
}
step_2_info() { echo "Download recommended motion version"; }
step_2() {
local motionUrl=
if [ "$SEQ_OSNAME" == "Raspbian" ]; then
motionUrl="https://github.com/Motion-Project/motion/releases/download/release-4.2.2/pi_${SEQ_DISTNAME}_motion_4.2.2-1_armhf.deb"
elif [ "$SEQ_OSNAME" == "Ubuntu" ]; then
motionUrl="https://github.com/Motion-Project/motion/releases/download/release-4.2.2/${SEQ_DISTNAME}_motion_4.2.2-1_amd64.deb"
fi
if [ "$motionUrl" == "" ]; then
echo " [W] Unsupported OS"
return 1
fi
exe wget -O "$motionDownload" $motionUrl
endReturn -o $? "Download motion failed"
}
motionDownload="/tmp/motion.deb"
step_3_info() { echo "Install downloaded motion version"; }
step_3() {
if [ ! -f "$motionDownload" ]; then
echo " [I] No downloaded motion found attempting download"
step 2
fi
exe dpkg -i "$motionDownload"
endReturn -o $? "Installing motion failed"
}
step_4_info() { echo "Upgrade python pip"; }
step_4_alias() { ALIAS="upgradepip"; }
step_4()
{
exe pip install --upgrade pip
endReturn -o $? "Upgrading pip failed"
}
step_5_info() { echo "Install $toolName"; }
step_5() {
exe pip install motioneye
endReturn -o $? "Installing $toolName failed"
}
step_6_info() { echo "Prepare configuration directory $toolCfgDir"; }
step_6() {
exe mkdir -p /etc/motioneye
saveReturn $?
exe cp "$motioneyeConfigSource" "$motioneyeConfigTarget"
saveReturn $?
endReturn "Creating first configuration failed"
}
motioneyeConfigSource="/usr/local/share/motioneye/extra/motioneye.conf.sample"
motioneyeConfigTarget="/etc/motioneye/motioneye.conf"
step_7_info() { echo "Create media directory $motioneyeMediaDir"; }
step_7() {
exe mkdir -p "$motioneyeMediaDir"
}
motioneyeMediaDir="/var/lib/motioneye"
step_8_info() { echo "Create $toolName service"; }
step_8() {
exe cp "$motioneyeServiceSource" "$motioneyeServiceTarget"
endReturn -o $? "Creating service failed"
exe systemctl daemon-reload
exe systemctl enable motioneye
exe systemctl start motioneye
}
motioneyeServiceSource="/usr/local/share/motioneye/extra/motioneye.systemd-unit-local"
motioneyeServiceTarget="/etc/systemd/system/motioneye.service"
step_20_info() { echo "Upgrade $toolName"; }
step_20_alias() { ALIAS="upgrade"; }
step_20() {
step "upgradepip"
exe pip install motioneye --upgrade
endReturn -o $? "Upgrading $toolName failed"
exe systemctl restart motioneye
}
VERSION_SEQREV=11
. /usr/local/bin/sequencer.sh

344
seqs/mysql.sh Executable file
View File

@@ -0,0 +1,344 @@
#!/bin/bash
# Mysql management using mariadb
databaseName="mariadb"
databasePackages="mariadb-server mariadb-client"
dbName=
dbUser=
dbRemote=localhost
dbPass=
step_1_info() {
echo "Installation of ${databaseName} packages:"
echoinfo "$databasePackages"
echoinfo "(Consider step \"latest\" first to setup official repository with the latest version)"
}
step_1_alias() { ALIAS=install; }
step_1() {
exe apt update
exe apt install $databasePackages
endReturn -o $? "Error instaling $databaseName"
}
step_2_info() { echo "Secure ${databaseName} installation"; }
step_2() {
exe mysql_secure_installation
}
step_3_info() { echo "${databaseName} configuration"; }
step_3() {
addConf -c "$mariadbConfig" "$mariadbConfigLoc"
echo -n "Restarting mysql ... "
exe service mysql restart && echo "ok"
}
mariadbConfigLoc="/etc/mysql/mariadb.conf.d/90-myconfig.cnf"
mariadbConfig="[mysqld]
innodb_large_prefix=on
innodb_file_format=barracuda
innodb_file_per_table=true
lower_case_table_names=0
# coming from friendica warning 2020.07
table_definition_cache=1400
#innodb_force_recovery=6"
step_8_info() { echo "Setup ubuntu $databaseName repository"; }
step_8_alias() { ALIAS="latest"; }
step_8() {
exe apt install curl
exep "curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash -s -- --skip-maxscale --skip-tools"
}
step_10_info() {
echoinfoArgs "[OPTIONS]"
echo "Create mysql database without specific characterset"
echoinfo " [OPTIONS]"
echoinfo " --charset,-c <utf8|utf8mb4> : character set and collate"
echoinfo " --database, -d : database name"
echoinfo " [OPTIONS] used in following steps"
echoinfo " --user, -u : user name"
echoinfo " Manual password entry for non existing user"
echoinfo " --remote, -r : ip of allowed remote host"
}
step_10_alias() { ALIAS="createdb"; }
step_10() {
local arg
local dbOption=
shift
for arg in "$@" ; do
case "$1" in
--charset|-c)
dbOption="$2"
shift 2;;
--database|-d)
dbName="$2"
shift 2 ;;
--user|-u)
dbUser="$2"
shift 2 ;;
--remote|-r)
dbRemote="$2"
shift 2 ;;
*)
break ;;
esac
done
case "$dbOption" in
utf8)
dbOption="CHARACTER SET utf8 COLLATE utf8_unicode_ci";;
utf8mb4)
dbOption="CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";;
*)
dbOption="";;
esac
if [ -z "$dbName" ] ; then
echo " [I] Existing mysql databases:"
exe mysql -u root -e 'SHOW DATABASES;'
read -p "Enter database name: " dbName
fi
endCheckEmpty dbName "database name"
exe mysql -u root -e 'CREATE DATABASE '$dbName' '"$dbOption"';'
endReturn -o $? "Cannot create database $dbName"
}
step_11_info() {
echoinfoArgs "[OPTIONS]"
echo "Create mysql user"
echoinfo " [OPTIONS]"
echoinfo " --user, -u : user name"
echoinfo " with manual password entry for non existing user"
echoinfo " --remote, -r : ip of allowed remote host"
}
step_11_alias() { ALIAS="createuser"; }
step_11() {
local arg
shift
for arg in "$@" ; do
case "$1" in
--charset|-c)
dbOption="$2"
shift 2;;
--database|-d)
dbName="$2"
shift 2 ;;
--user|-u)
dbUser="$2"
shift 2 ;;
--remote|-r)
dbRemote="$2"
shift 2 ;;
*)
break ;;
esac
done
if [ -z "$dbUser" ] ; then
echo " [I] Existing mysql user:"
exe mysql -u root -e 'SELECT User, Host FROM mysql.user;'
read -p "Enter mysql user name: " dbUser
fi
endCheckEmpty dbUser "user name"
if ! echo "SELECT COUNT(*) FROM mysql.user WHERE user = '$dbUser' AND host = '$dbRemote';" | mysql | grep 1 &>/dev/null; then
# User does not exist
if [ $DRY -eq 0 ]; then
read -s -p "Enter mysql user password: " dbPass
endCheckEmpty dbPass "password"
else
echoseq "Enter mysql password: ...skipped..."
fi
exe mysql -u root -e 'CREATE USER '"'"$dbUser"'"'@'"'"$dbRemote"'"' IDENTIFIED BY '"'"$dbPass"'"';'
endReturn -o $? "Error creating mysql user"
fi
}
step_12_info() {
echoinfoArgs "[OPTIONS]"
echo "Grant privileges"
echoinfo " [OPTIONS]"
echoinfo " --database, -d : 'database name'.*"
echoinfo " --user, -u : user name"
echoinfo " --remote, -r : ip of allowed remote host"
}
step_12_alias() { ALIAS="grant"; }
step_12() {
local arg
shift
for arg in "$@" ; do
case "$1" in
--charset|-c)
dbOption="$2"
shift 2;;
--database|-d)
dbName="$2"
shift 2 ;;
--user|-u)
dbUser="$2"
shift 2 ;;
--remote|-r)
dbRemote="$2"
shift 2 ;;
*)
break ;;
esac
done
exe mysql -u root -e 'GRANT ALL PRIVILEGES ON '$dbName'.* TO '"'"$dbUser"'"'@'"'"$dbRemote"'"';'
endReturn -o $? "Error assigning privileges on database"
exe mysql -u root -e 'FLUSH PRIVILEGES;'
}
step_14_info() {
echoinfoArgs "[OPTIONS]"
echo "Revoke all granted privilegs"
echoinfo " [OPTIONS]"
echoinfo " --user, -u : user name"
echoinfo " --remote, -r : ip of allowed remote host"
}
step_14_alias() { ALIAS="revokeall"; }
step_14() {
local arg
shift
for arg in "$@" ; do
case "$1" in
--user|-u)
dbUser="$2"
shift 2 ;;
--remote|-r)
dbRemote="$2"
shift 2 ;;
*)
break ;;
esac
done
exe mysql -u root -e 'REVOKE ALL, GRANT OPTION FROM '"'"$dbUser"'"'@'"'"$dbRemote"'"';'
endReturn -o $? "Error revoking privileges for user $dbUser"
exe mysql -u root -e 'FLUSH PRIVILEGES;'
}
step_30_info() { echo "List mysql databases"; }
step_30_alias() { ALIAS="listdb"; }
step_30() {
exe mysql -u root -e 'SHOW DATABASES;'
echo -e "\nDrop userdb by: mysql -u root -e 'DROP DATABASE userdb;'"
}
step_32_info() { echo "List mysql user"; }
step_32_alias() { ALIAS="listuser"; }
step_32() {
exe mysql -u root -e 'SELECT User, Host FROM mysql.user;'
echo -e "\nDrop dbuser by: mysql -u root -e 'DROP USER dbuser@localhost;'"
}
step_34_info() {
echoinfoArgs "[OPTIONS]"
echo "Show privileges"
echoinfo " [OPTIONS]"
echoinfo " --user, -u : user name"
echoinfo " --remote, -r : ip of allowed remote host"
}
step_34_alias() { ALIAS="listprivileges"; }
step_34() {
local arg
shift
for arg in "$@" ; do
case "$1" in
--user|-u)
dbUser="$2"
shift 2 ;;
--remote|-r)
dbRemote="$2"
shift 2 ;;
*)
break ;;
esac
done
exe mysql -u root -e 'SHOW GRANTS FOR '"'"$dbUser"'"'@'"'"$dbRemote"'"';'
}
step_36_info() {
echoinfoArgs "[DATABASE_NAME]"
echo "Size of database"
}
step_36_alias() { ALIAS="sizedb"; }
step_36() {
if [ -z "$2" ]; then
echo "Please provide a database name. e.g. $0 sizedb mydb_db"
else
exe mysql -u root -e 'SELECT table_schema "DB Name",
ROUND(SUM(data_length + index_length) / 1024 / 1024, 1) "DB Size in MB"
FROM information_schema.tables
WHERE table_schema="'$2'"
GROUP BY table_schema;'
fi
}
step_50_info() {
echoinfoArgs "<DATABASE NAME> <TARGET DIR>"
echo "Backup (dump) a mysql database"
}
step_50_alias() { ALIAS="backup"; }
step_50() {
shift # step number not used
if [ -z $1 ] ; then
echoerr " [E] No database name provided"
return 1
fi
local dbName="$1"
local buTarget="$2"
if [ -z "$2" ] ; then
echoerr " [W] No target directory provided. Using home of current user"
buTarget="$HOME"
elif [ ! -e "$2" ]; then
endReturn -o 1 -f "$2 does not exist"
fi
echo " [I] Dumping database $dbName to $buTarget"
exep "mysqldump --single-transaction $dbName > \"$(realpath $buTarget)/${dbName}_backup_$(date +%Y%m%d-%H%M%S).sql\""
endReturn -o $? "Error creating $dbName backup"
}
step_52_info() { echo "Restore a mysql database"; }
step_52_alias() { ALIAS="restore"; }
step_52() {
echo "Restore with:"
echo " mysql -e \"DROP DATABASE nextcloud_db\""
echo " mysql -e \"CREATE DATABASE nextcloud_db\""
echo " mysql nextcloud_db < NextcloudBackup_DB_20170912.sql"
}
# Read database information dbname/user/pass if empty
readDatabaseInfos() {
if [ "$dbName" == "" ] ; then
read -p "Enter postgres database name: " dbName
endCheckEmpty dbName "database"
fi
if [ "$dbUser" == "" ] ; then
read -p "Enter postgres user name: " dbUser
endCheckEmpty dbUser "user name"
fi
if [ "$dbPass" == "" ] ; then
read -s -p "Enter postgres password: " dbPass
endCheckEmpty postgresPass "password"
fi
echo
}
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,5 @@
# Configuration file for nextcloud sequence
sc_ncServerUser="www-data"
sc_ncInstallDir="/var/www/nextcloud"
sc_ncDataDir="${sc_ncInstallDir}/data"

140
seqs/nextcloud.sh Executable file
View File

@@ -0,0 +1,140 @@
#!/usr/bin/env bash
# Dependency to other seqs
# - mysql.sh (soft; Missing informational output)
toolName="nextcloud"
localOcc=("echo" "occ not found!")
# Get script working directory
# (when called from a different directory)
sq_dir="$( cd "$( dirname -- "$(realpath "${BASH_SOURCE[0]}")")" >>/dev/null 2>&1 && pwd )"
sq_config=0
sq_configFileName="${toolName}.cfg"
sq_configFileTemplate="$sq_dir/${sq_configFileName}.example"
step_config() {
## or to use sequencer api:
initSeqConfig "$sq_configFileName" "$sq_configFileTemplate"
if [ $? -eq 0 ] ; then
sq_config=1
fi
localOcc=( sudo -u $sc_ncServerUser php "$(escpath "$sc_ncInstallDir/occ")" )
}
step_1_info() {
echoinfoArgs "[OCC ARGS]"
echo "Execute occ command"
}
step_1_alias() { ALIAS="occ"; }
step_1() {
shift
exe "${localOcc[@]}" "$@"
}
step_20_info() { echo "Upgrade $toolName on command line to latest version of selected release channel"; }
step_20_alias() { ALIAS="upgrade"; }
step_20() {
if [ $sq_config -eq 0 ] ; then
echoerr " [E] No configuration found to determine installation directory"
return 1
fi
exe cd "$sc_ncInstallDir"
exe sudo -u www-data php "$ncInstaller"
}
ncInstaller="updater/updater.phar"
step_102_info() { echoinfoArgs "<NC DATABASE> <IPV4 ADDRESS>"; echo "Delete IP from bruteforce table"; }
step_102_alias() { ALIAS="bruteforceRemoveIP"; }
step_102() {
shift
local ncdb=
local ip=
local ipregex='^[0-2]*[0-9]{1,2}\.[0-2]*[0-9]{1,2}\.[0-2]*[0-9]{1,2}\.[0-2]*[0-9]{1,2}$'
if [ -z $1 ] ; then
echoerr " [E] No database provided"
if [ -f "${sq_dir}/mysql.sh" ] ; then
echo " [I] Available mysql databases:"
"${sq_dir}/mysql.sh" -qq listdb
fi
return 1
else
ncdb="$1"
fi
# Check if string looks like ipv4 address
if [[ "$2" =~ $ipregex ]] ; then
ip="$2"
else
echoerr " [E] No valid IP:PORT detected: $2"
return 1
fi
exe mysql -u root -D ${ncdb} -e 'delete FROM oc_bruteforce_attempts WHERE IP="'${ip}'";'
endReturn -o $? "Error deleting ip $ip"
}
step_104_info() { echoinfoArgs "<USER>"; echo "Reset and rescan the music library in the background for one user"; }
step_104_alias() { ALIAS="audioreset"; }
step_104() {
shift
local ncUser=$1
if [ -z "$ncUser" ] ; then
echoerr " [E] Reset only for single user"
return 1
fi
exep "${localOcc[@]} audioplayer:reset $ncUser > /var/log/ncAudioRescan.log"
echoseq " [I] Rescan audioplayer database for user $ncUser"
exep "${localOcc[@]} audioplayer:scan -vvvv $ncUser >> /var/log/ncAudioRescan.log &"
}
step_106_info() { echoinfoArgs "<USER>"; echo "Scan the music library"; }
step_106_alias() { ALIAS="audioscan"; }
step_106() {
shift
local ncUser=$1
if [ -z "$ncUser" ] ; then
echoerr " [E] Reset only for single user"
return 1
fi
exe "${localOcc[@]}" audioplayer:scan -vvvv $ncUser
}
step_110_info() { echo "Reset picture preview folder"; }
step_110_alias() { ALIAS="resetpreview"; }
step_110() {
if [ -e "${sc_ncDataDir}" ]; then
exe rm -rf "${sc_ncDataDir}/appdata_"*"/preview/"*
echoseq " [I] Rescan app data folder"
exep "${localOcc[@]} files:scan-app-data &"
else
echoerr " [E] Nextcloud data direcotry $sc_ncDataDir not found"
return 1
fi
}
step_200_alias() { ALIAS="notes"; }
step_200() {
outColor green
cat<<NOTES_END
# Recommended preview settings
[$sc_ncInstallDir/config/config.php]
occ config:app:set previewgenerator squareSizes --value="32 256"
occ config:app:set previewgenerator widthSizes --value="256 384"
occ config:app:set previewgenerator heightSizes --value="256"
occ config:system:set preview_max_x --value 2048
occ config:system:set preview_max_y --value 2048
occ config:system:set jpeg_quality --value 60
occ config:app:set preview jpeg_quality --value="60"
NOTES_END
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh

76
seqs/olivetin.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/bash
toolName=olivetin
latestUrl="https://api.github.com/repos/OliveTin/OliveTin/releases/latest"
latestVersion=
tempExtract=
tempInstall=
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
## or to use sequencer api with global config file:
#initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
## or to use sequencer api with profile config file support:
#initSeqConfig -p "$SCRIPT_NAME" "$CONFIG_FILE_TEMPLATE"
#if [ $? -eq 0 ] ; then
# CONFIG=1
#else
# # End if no configuration file exists
# [ $DRY -eq 0 ] && return -1
#fi
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && APTOPT="-y"
## Return of non zero value will abort the sequence
return 0
}
step_1_info() { echo "Install $toolName"; }
step_1_alias() { ALIAS="install"; }
step_1() {
downloadLatest
if [ -e "$tempInstall" ]; then
exe dpkg -i "$tempInstall"
exe systemctl --now enable OliveTin
fi
}
fetchLatestVersion() {
if [ ! -z $latestVersion ] ; then
return 0
fi
latestVersion=$(curl --silent "$latestUrl" | grep -Po '"tag_name": "\K.*(?=")')
}
downloadLatest() {
fetchLatestVersion
local downUrl="https://github.com/OliveTin/OliveTin/releases/download/${latestVersion}/OliveTin_${latestVersion}_linux_armv7.deb"
if [ ! -e "$tempInstall" ] ; then
exe mkdir -p "$tempDown"
exe wget -O "$tempInstall" $downUrl
endReturn -o $? "Download failed: $downUrl"
else
echo " [I] Found existing download: $tempInstall"
fi
}
tempDown="/tmp/olivetin"
tempInstall="$tempDown/olivetin.deb"
VERSION_SEQREV=13
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,8 @@
#!/bin/bash
onlyOfficePort="80"
dockerDns1="80.241.218.68" # https://dismail.de/info.html#dns
dockerDns2="46.182.19.48" # https://digitalcourage.de/support/zensurfreier-dns-server
dockerDefaultConf="/etc/default/docker"
dockerImageName="onlyoffice/documentserver"
dockerSecret=

194
seqs/onlyoffice.sh Executable file
View File

@@ -0,0 +1,194 @@
#!/bin/bash
# Source
# Docker - Install using the repository
# https://docs.docker.com/install/linux/docker-ce/ubuntu/
#
# Onlyoffice - Docker
# https://helpcenter.onlyoffice.com/server/docker/document/docker-installation.aspx
toolName="onlyoffice"
dockerDeps="apt-transport-https ca-certificates curl gnupg-agent software-properties-common"
dockerGpgKeyUrl="https://download.docker.com/linux/ubuntu/gpg"
dockerRepoUrl="https://download.docker.com/linux/ubuntu"
dockerPackages="docker-ce docker-ce-cli containerd.io"
# Entry in config value $dockerDefaultConf
dockerDnsEntry=
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
## Called once before executing steps.
## e.g. to source a config file manually:
#. "$CONFIG_FILE"
## or to use sequencer api with global config file:
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
## or to use sequencer api with profile config file support:
#initSeqConfig -p "$SCRIPT_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return -1
fi
## Apt cmdline option to suppress user interaction
[ $QUIET -ne 0 ] && APTOPT="-y"
dockerDnsEntry="DOCKER_OPTS=\"--dns $dockerDns1 --dns $dockerDns2\""
## Return of non zero value will abort the sequence
return 0
}
step_1_info() { echo "Install Docker dependencies"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
exe apt install $dockerDeps $APTOPT
endReturn -o $? "Docker dependencies installation failed"
}
step_2_info() { echo "Install Docker repository"; }
step_2() {
# Add official docker GPG key
exep "curl -fsSL ${dockerGpgKeyUrl} | sudo apt-key add -"
# Add stable repository
exe add-apt-repository "deb [arch=amd64] ${dockerRepoUrl} $(lsb_release -cs) stable"
endReturn -o $? "Failed to add Docker repository"
exe apt update
endReturn -o $? "Docker repository not available"
}
step_3_info() { echo "Install latest Docker version"; }
step_3() {
# Install the latest version
if [ $QUIET -ne 0 ] ; then
aptOption="-y"
else
aptOption=""
fi
exe apt install $dockerPackages $aptOption
echo " [I] You may test the installation by running:"
echo " sudo docker run hello-world"
}
step_4_info() { echo "Replace Docker DNS entry"; }
step_4() {
exe sed -i "s/\(^#DOCKER_OPTS=.*\)$/#\1\n${dockerDnsEntry}/" "$dockerDefaultConf"
exep "grep \"${dockerDns1}\" \"$dockerDefaultConf\" >>/dev/null"
if [ $? -ne 0 ] ; then
echoerr " [W] Docker dns entry could not be changed"
fi
}
step_5_info() {
echoinfoArgs "[SECRET]"
echo "Install/start onlyoffice docker container"
echoinfo "If [SECRET] is empty, user input will be available if not run --quiet."
echoinfo "$toolName will be run unsecured if no secret was provied."
}
step_5_alias() { ALIAS="startoo"; }
step_5() {
local options=
local secret=
if [ ! -z "$2" ] ; then
secret="$2"
elif [ ! -z "$dockerSecret" ]; then
secret="$dockerSecret"
elif [ $QUIET -eq 0 ] ; then
exe read -s -p "JWT Secret: " secret
fi
# The correct expansion for missing SECRET or SECRET with spaces is not possible.
# Therefore docker without secret needs to be called separately
if [ ! -z "$secret" ] ; then
options="-e JWT_ENABLED=true -e JWT_SECRET="
# This is the only way to provide SECRET($2) to docker command line which handles all types of characters.
exe docker run -i -t -d -p ${onlyOfficePort}:80 ${options}"$secret" --restart=always \
-v /app/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \
-v /app/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data \
-v /app/onlyoffice/DocumentServer/lib:/var/lib/onlyoffice \
-v /app/onlyoffice/DocumentServer/db:/var/lib/postgresql "${dockerImageName}"
else
echoerr " [W] Running $toolName without JWT (JSON Web Tokens)"
exe docker run -i -t -d -p ${onlyOfficePort}:80 --restart=always "${dockerImageName}"
fi
unset secret
}
step_7_info() { echo "Upgrade $toolName to latest version"; }
step_7_alias() { ALIAS="upgrade"; }
step_7() {
# get container ID
local containerId=$(docker ps -aqf ancestor="$dockerImageName")
if [ ! -z $containerId ] ; then
exe docker stop $containerId
exe docker rm $containerId
else
echoerr " [W] No $toolName Docker container found"
fi
exe docker pull $dockerImageName
endReturn -o $? "Error getting $toolName Docker update"
step startoo
}
step_10_info() { echo "List running Docker container"; }
step_10_alias() { ALIAS="ls"; }
step_10() {
exe docker container ls
echo
echo " [I] To stop a container run:"
echo " docker stop [CONTAINER ID]"
echo " e.g.: docker stop 70f1c5c81be2"
}
step_12_info() {
echo "Clean unused Docker data"
echoinfo "(unused containers, dangling images, networks, build cache and volumes)"
}
step_12_alias() { ALIAS="prune"; }
step_12() {
exe docker system df
exe docker system prune
exe docker volume prune
}
step_100_info() { echo "Uninstall Docker"; }
step_100_alias() { ALIAS="uninstall"; }
step_100() {
exe apt-get purge docker-ce
}
step_102_info() { echo "Purge images, containers, volumes, or customized configuration files"; }
step_102_alias() { ALIAS="purge"; }
step_102() {
exe read -p "Are you sure y/[n]? " answer
case $answer in
[yY])
exe service docker stop
exe rm -rf /var/lib/docker
;;
*)
return 0
;;
esac
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh

59
seqs/openvpn.sh Executable file
View File

@@ -0,0 +1,59 @@
#!/bin/bash
toolName=openvpn
toolDeps=openvpn
toolDefaultConf="/etc/default/openvpn"
toolUserScriptsLoc="/usr/lib/openvpn"
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_FILE=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_FILE%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
CONFIG_DIR="$WDIR/$SCRIPT_NAME"
step_config() {
#echo "Called once before executing steps."
## e.g. to source a config file manually:
#. "$CONFIG_FILE"
## or to use sequencer api with global config file:
#initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
## or to use sequencer api with profile config file support:
#initSeqConfig -p "$SCRIPT_NAME" "$CONFIG_FILE_TEMPLATE"
#if [ $? -eq 0 ] ; then
# CONFIG=1
#else
# # End if no configuration file exists
# [ $DRY -eq 0 ] && return -1
#fi
[ $QUIET -ne 0 ] && APTOPT="-y"
return 0
}
step_1_info() { echo "Install $toolName"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
exe apt install $toolDeps $APTOPT
}
step_2_info() { echo "Install customized helper scripts to $toolUserScriptsLoc"; }
step_2() {
exep "mkdir \"$toolUserScriptsLoc\" 2>>/dev/null"
[ $? -ne 0 ] && \
echoseq " [W] $toolUserScriptsLoc already exists. Not overwriting existing files."
exe cp -n "$CONFIG_DIR"/* "$toolUserScriptsLoc"
}
step_10_info() { echo "Open openvpn system start configuration"; }
step_10_alias() { ALIAS="default"; }
step_10() {
exe vi "$toolDefaultConf"
}
VERSION_SEQREV=12
. /usr/local/bin/sequencer.sh

5
seqs/openvpn/down.sh Executable file
View File

@@ -0,0 +1,5 @@
#! /bin/bash
echo "Restoring original nameservers"
rm -f /etc/resolv.conf
cp -f /etc/resolv.conf.default /etc/resolv.conf
echo "Done restoring nameservers cheers"

22
seqs/openvpn/my.conf Normal file
View File

@@ -0,0 +1,22 @@
# Set output verbosity (3 recommended by openvpn)
# 0 -- No output except fatal errors.
# 1 to 4 -- Normal usage range.
# 5 -- Output R and W characters to the console for each packet read
# and write, uppercase is used for TCP/UDP packets and lowercase is
# used for TUN/TAP packets.
# 6 to 11 -- Debug info range (see errlevel.h for additional informtion
verb 1
# Always add custom nameserver
#dhcp-option DNS 208.67.222.222
#dhcp-option DNS 84.200.69.80
# Mute common false alarm on WiFi networks
mute-replay-warnings
# Allow openvpn to call user defined scripts
script-security 2
# Execute our custom up and down scripts
up /usr/lib/openvpn/vpn-up
down /usr/lib/openvpn/vpn-down

38
seqs/openvpn/up.sh Executable file
View File

@@ -0,0 +1,38 @@
#! /bin/bash
DEV=$1
if [ ! -d /tmp/openvpn ]; then
mkdir /tmp/openvpn
fi
CACHE_NAMESERVER="/tmp/$DEV.nameserver"
echo -n "" > $CACHE_NAMESERVER
TEMP_LOG="/tmp/openvpn_dns.log"
echo "DNS openvpn" > "$TEMP_LOG"
echo -e "${foreign_option_1}\n${foreign_option_2}\n$foreign_option_3" >> "$TEMP_LOG"
rm -rf /tmp/resolv.conf
touch /tmp/resolv.conf
dns=dns
for opt in ${!foreign_option_*}
do
eval "echo \$$opt" >> "$TEMP_LOG"
eval "dns=\${$opt#dhcp-option DNS }"
if [[ $dns =~ [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]; then
if [ ! -f /etc/resolv.conf.default ]; then
cp /etc/resolv.conf /etc/resolv.conf.default
fi
# don't add "local" dns server
#cat /etc/resolv.conf | grep -v ^# | grep -v ^nameserver > /tmp/resolv.conf
echo "nameserver $dns" >> /tmp/resolv.conf
echo $dns >> $CACHE_NAMESERVER
#cat /etc/resolv.conf | grep -v ^# | grep -v "nameserver $dns" | grep nameserver >> /tmp/resolv.conf
fi
done
if [ -e "/tmp/resolv.conf" ]; then
mv /tmp/resolv.conf /etc/resolv.conf
fi

13
seqs/openvpn/vpn-down Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
# Manage nameserver with resolvconf
#/etc/openvpn/update-resolv-conf
# Manage nameserver with /etc/resolv.conf only
#/usr/lib/openvpn/down.sh $@
# Delete route to internal network
#/usr/sbin/ip route del 10.5.0.0/24 via 192.168.0.20 dev eth0
# Stop services only active while vpn is connected
/usr/lib/openvpn/vpn-services stop

15
seqs/openvpn/vpn-services Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
# Default or unrecognized stops the listed services
serviceOp="stop"
serviceCtl="$(command -v systemctl) -q"
case $1 in
start|restart|stop)
serviceOp="$1";;
*)
>&2 echo "Unrecognized argument. Stopping services"
serviceOp="stop";;
esac
#"$serviceCtl" $serviceOp danted

16
seqs/openvpn/vpn-up Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
# Make sure firewall is active
#ufw --force enable
# Manage nameserver with resolvconf
#/etc/openvpn/update-resolv-conf
# Manage nameserver with /etc/resolv.conf only
#/usr/lib/openvpn/up.sh $@
# Add route to internal network
#/usr/sbin/ip route add 10.5.0.0/24 via 192.168.0.20 dev eth0
# Start services only active while vpn is connected
/usr/lib/openvpn/vpn-services start

32
seqs/paperless.sh Executable file
View File

@@ -0,0 +1,32 @@
#!/bin/bash
step_1_info() { echo "Install python3"; }
step_1() {
exe apt update
exe apt install python3 python3-pip
}
step_2_info() { echo "Get paperless using git (checkout 2.7.0)"; }
step_2() {
exe git clone https://github.com/the-paperless-project/paperless.git /opt/paperless
exe cd /opt/paperless && git checkout 2.7.0
}
step_3_info() { echo "Install other dependcies"; }
step_3() {
exe apt install gnupg tesseract-ocr tesseract-ocr-deu imagemagick unpaper libpoppler-cpp-dev optipng
exe pip3 install --user --requirement /opt/paperless/requirements.txt
}
step_4_info() { echo "Paperless configuration file"; }
step_4() {
if [ ! -f /etc/paperless.conf ] ; then
cp -ar paperless.conf.example /etc/paperless.conf
else
echo "[ WARN ] Configuration already exists. Doing nothing"
fi
}
VERSION_SEQREV=3
. sequencer.sh

5
seqs/piwigo.cfg.example Normal file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
PIWI_DIR="/var/www/piwigo"
PIWI_BU_DIR="/root/backup/piwigodb"
PIWI_DB_NAME="piwigo29_db"

52
seqs/piwigo.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/bin/bash
#
## Installation and management of piwigo gallery
toolName="piwigo"
toolVersion="11.3.0"
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd )"
CONFIG=0
SCRIPT_NAME=$(basename -- "$0")
SCRIPT_NAME=${SCRIPT_NAME%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
[ $DRY -eq 0 ] && return 1
fi
}
step_30_info() { echo "Backup ${toolName} web direcotry"; }
step_30_alias() { ALIAS="backup"; }
step_30() {
exep "cd \"${PIWI_DIR}\"/.. && tar czf \"${PIWI_BU_DIR}/\`date +%Y%m%d\`_${toolName}_web.tar.gz\" --exclude=\"${toolName}/network/*\" --exclude=\"${toolName}/_data/i/*\" \"$(basename "$PIWI_DIR")\""
}
step_31_info() {
echoinfoArgs "[daily|monthly(default]"
echo "Backup ${toolName} database"
}
step_31_alias() { ALIAS="backupdb"; }
step_31() {
case "$2" in
daily|Daily|DAILY)
[ $QUIET -ne 2 ] && echo " [I] Daily backup..."
exep "mysqldump --single-transaction -u root ${PIWI_DB_NAME} | bzip2 -c > \"${PIWI_BU_DIR}/${toolName}_daily.sql.bz2\""
;;
*)
[ $QUIET -ne 2 ] && echo " [I] Monthly backup..."
exep "mysqldump --single-transaction -u root ${PIWI_DB_NAME} | bzip2 -c > \"${PIWI_BU_DIR}/monthly/\`date +%Y%m%d\`_${toolName}.sql.bz2\""
;;
esac
}
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

278
seqs/pixelfed.sh Executable file
View File

@@ -0,0 +1,278 @@
#!/bin/bash
toolName="pixelfed"
toolTag="dev"
toolDeps="composer jpegoptim php7.3-bcmath php-imagick"
toolPath="/var/www/pixelfed"
step_1_info() { echo "Updating apt"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
}
step_2_info() { echo -e "Installing $toolName dependencies: $toolDeps"; }
step_2() {
exe apt install $toolDeps -y
endReturn -o $? "Installing deps for $toolName failed"
exe service php7.3-fpm restart
endReturn -o $? "Problems starting $toolName"
}
step_3_info() { echo -e "Get $toolName using git"; }
step_3() {
exe git clone -b $toolTag https://github.com/pixelfed/pixelfed.git $toolPath
exe cd $toolPath
exe chown -R www-data:www-data . # change user/group to http user and http group
exe find . -type d -exec chmod 755 {} \; # set all directories to rwx by user/group
exe find . -type f -exec chmod 644 {} \; # set all files to rw by user/group
exe composer install --no-ansi --no-interaction --optimize-autoloader
endReturn -o $? "Composer install error"
}
step_4_info() { echo "Create mysql database for $toolName"; }
step_4() {
local mysqlDatabase
local mysqlUser
local mysqlPass
echo "Existing mysql databases:"
exe mysql -u root -e 'SHOW DATABASES;'
echo -en "Enter database name: "
exe read mysqlDatabase
endCheckEmpty mysqlDatabase "database name"
exe mysql -u root -e 'CREATE DATABASE '$mysqlDatabase' CHARACTER SET utf8mb4;'
endReturn -o $? "Creating database failed"
echo "Existing mysql user:"
exe mysql -u root -e 'SELECT User, Host FROM mysql.user;'
echo -en "Enter mysql user name: "
read mysqlUser
endCheckEmpty mysqlDatabase "user name"
echo -en "Enter mysql user password: "
read -s mysqlPass
endCheckEmpty mysqlPass "password"
exe mysql -u root -e 'CREATE USER '"'"$mysqlUser"'"'@'"'"'localhost'"'"' IDENTIFIED BY '"'"$mysqlPass"'"';'
endReturn -o $? "Creating database user \"${mysqlUser}\" failed";
exe mysql -u root -e 'GRANT ALL PRIVILEGES ON '$mysqlDatabase'.* TO '"'"$mysqlUser"'"'@'"'"'localhost'"'"';'
endReturn -o $? "Granting privileges for user \"${mysqlUser}\" failed";
exe mysql -u root -e 'FLUSH PRIVILEGES;'
}
step_5_info() { echo "$toolName configuration"; }
step_5() {
exe cd $toolPath
exe cp .env.example .env
exe read -p "Edit database settings, hostname, email settings, IMAGE_DRIVER=imagick, etc... (Enter to continue)"
exe vi .env
exe php artisan key:generate
exe php artisan config:cache
exe php artisan storage:link
exe php artisan migrate --force
exe php artisan route:cache
# Needed for using oauth (app like pixeldroid)
# https://github.com/pixelfed/pixelfed/issues/2654
exe php artisan passport:install
}
step_6_info() { echo "Create admin user"; }
step_6() {
exe cd $toolPath
exe read -p "Create admin user. (Enter to continue)"
exe php artisan user:create
}
step_7_info() { echo "Create pixelfed (horzion) service"; }
step_7() {
addConf -c "${horizonService}" "${horizonServiceLoc}"
endReturn -o $? "Failed to add horizon service"
exe systemctl daemon-reload
exe systemctl enable pixelfed.service
exe service pixelfed start
}
horizonServiceLoc="/etc/systemd/system/pixelfed.service"
horizonService="\
[Unit]
Description=${toolName}s' Horizon
After=syslog.target
After=network.target
#Requires=mysql.service
Requires=mariadb.service
#Requires=postgresql.service
#Requires=memcached.service
#Requires=redis.service
[Service]
# Modify these two values and uncomment them if you have
# repos with lots of files and get an HTTP error 500 because
# of that
###
#LimitMEMLOCK=infinity
#LimitNOFILE=65535
RestartSec=2s
Type=simple
User=www-data
Group=www-data
WorkingDirectory=${toolPath}/
ExecStart=/usr/bin/php ${toolPath}/artisan horizon
Restart=always
Environment=
[Install]
WantedBy=multi-user.target"
step_8_info() { echo "Create scheduler cron job"; }
step_8_alias() { ALIAS="scheduler"; }
step_8() {
addConf -s "$schedulerCmd" "$schedulerCron"
}
schedulerCron="/etc/cron.d/pixelfedScheduler"
schedulerCmd="* * * * * cd ${toolPath} && php artisan schedule:run >>/dev/null 2>&1"
step_9_info() { echo "Nginx configuration"; }
step_9() {
addConf -c "$nginxConfig" "$nginxConfigLoc"
exe ln -s "$nginxConfigLoc" "$nginxConfigEnable"
exe nginx -t
endReturn -o $? "Nginx configuration check error"
exe service nginx restart
}
nginxConfigLoc="/etc/nginx/sites-available/pixelfed"
nginxConfigEnable="/etc/nginx/sites-enabled/pixelfed"
nginxConfig="\
upstream php-handler-pixel {
server unix:/var/run/php/php7.3-fpm.sock;
}
map \$http_x_forwarded_proto \$proxy_https {
default '';
https 'on';
}
server {
listen 80;
listen [::]:80;
add_header X-Frame-Options \"SAMEORIGIN\";
add_header X-XSS-Protection \"1; mode=block\";
add_header X-Content-Type-Options \"nosniff\";
# Path to the root of your installation
root ${toolPath}/public;
index index.html index.htm index.php;
charset utf-8;
client_max_body_size 64M;
location / {
try_files \$uri \$uri/ /index.php?\$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \\.php$ {
try_files \$uri =404;
fastcgi_split_path_info ^(.+\\.php)(/.+)$;
fastcgi_pass php-handler-pixel;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME \$request_filename;
fastcgi_param PATH_INFO \$fastcgi_path_info;
# fix preview problem
fastcgi_param REQUEST_SCHEME \$http_x_forwarded-proto;
fastcgi_param HTTPS \$proxy_https if_not_empty;
}
location ~ /\\.(?!well-known).* {
deny all;
}
}"
step_20_info() { echo "Reload configuration (.env)"; }
step_20_alias() { ALIAS="newenv"; }
step_20() {
exe cd $toolPath
exe php artisan config:cache
exe service pixelfed restart
}
step_22_info() { echo "Create new user"; }
step_22_alias() { ALIAS="createuser"; }
step_22() {
exe cd $toolPath
exe php artisan user:create
}
step_24_info() { echo "Checkout to dev branch. Losing local changes!"; }
step_24_alias() { ALIAS="forcedev"; }
step_24() {
exe read -p "Are you sure: y/[n]? " answer
if [ $DRY -eq 0 ] ; then
case $answer in
[yY])
;;
*)
return 1
;;
esac
fi
exe cd $toolPath
exe git fetch --all
exe git reset --hard origin/dev
exe git pull origin dev
exe git checkout dev
}
step_100_info() { echo "Upgrade \"${toolPath}\" to supported tag $toolTag"; }
step_100_alias() { ALIAS="upgrade"; }
step_100() {
exe cd $toolPath
exe git pull origin $toolTag
endReturn -o $? "git pull failed"
exe git checkout $toolTag
endReturn -o $? "git checkout failed"
}
step_101_info() { echo "Recommended post update procedure"; }
step_101_alias() { ALIAS="postupdate"; }
step_101() {
exe cd $toolPath
exe composer install
exe php artisan config:cache
exe php artisan route:cache
exe php artisan view:cache
exe php artisan cache:clear
exe php artisan migrate --force
exe php artisan horizon:purge
exe php artisan horizon:publish
exe php artisan storage:link
exe php artisan instance:actor
echo -n " [I] Restarting pixelfed horzion service..."
exe service pixelfed restart && echo "ok"
}
# Src: https://docs.pixelfed.org/running-pixelfed/troubleshooting.html
step_102_info() { echo "Fix if horizon services is running but not showing the administration interface"; }
step_102_alias() { ALIAS="fixhorizon"; }
step_102() {
exe cd $toolPath
exe php artisan package:discover
exe php artisan horizon:install
exe php artisan route:cache
echo -n " [I] Restarting pixelfed horzion service..."
exe service pixelfed restart && echo "ok"
}
# Sequence Revision
VERSION_SEQREV=7
# Path to sequencer
. sequencer.sh

View File

@@ -0,0 +1,9 @@
#!/bin/bash
# Postfixamdin configuration
PFA_SRV_LOC="/srv/postfixadmin"
PFA_WEB_LOC="/var/www/pfa"
PFA_DATABASE="pfa_db"
PFA_BACKUP="/root/backup/pfa"
PFA_PHP_VERSION="7.3"

328
seqs/postfixadmin.sh Executable file
View File

@@ -0,0 +1,328 @@
#!/bin/bash
toolName=postfixadmin
toolPhpDeps='php${PFA_PHP_VERSION}-fpm php${PFA_PHP_VERSION}-imap php${PFA_PHP_VERSION}-mbstring php${PFA_PHP_VERSION}-mysql php${PFA_PHP_VERSION}-json php${PFA_PHP_VERSION}-curl php${PFA_PHP_VERSION}-zip php${PFA_PHP_VERSION}-xml php${PFA_PHP_VERSION}-bz2 php${PFA_PHP_VERSION}-intl php${PFA_PHP_VERSION}-gmp'
toolConfName="config.local.php"
toolTemplates="templates_c"
toolTemplatesLoc="$PFA_SRV_LOC/$toolTemplates"
toolAdditionsLoc="$PFA_SRV_LOC/ADDITIONS"
latestUrl="https://api.github.com/repos/$toolName/$toolName/releases/latest"
fetchmailUser="fetchmail"
fetchmailDeps="fetchmail liblockfile-simple-perl"
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="${toolName}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
echo " ${toolName} path: ${PFA_WEB_LOC}"
echo " ${toolName} backup: ${PFA_BACKUP}"
echo " php Version: ${PFA_PHP_VERSION}"
CONFIG=1
fi
}
step_1_info() {
# eval needed to expand sourced configuration variables
local localDeps=`eval "echo \"$toolPhpDeps\""`
echo "Install $toolName dependencies:"
echoinfo "$localDeps"
}
step_1_alias() { ALIAS="install"; }
step_1() {
# eval needed to expand sourced configuration variables
local localDeps=`eval "echo \"$toolPhpDeps\""`
local aptOpt=
if [ $QUIET -ne 0 ];then
aptOpt="-y"
fi
exe apt update
exe apt install $localDeps $aptOpt
}
step_2_info() { echo "Install $toolName to $PFA_SRV_LOC"; }
step_2() {
step upgrade
}
step_3_info() { echo "Install fetchmail"; }
step_3_alias() { ALIAS="install_fetchmail"; }
step_3() {
local aptOpt=
if [ $QUIET -ne 0 ];then
aptOpt="-y"
fi
exe apt install $fetchmailDeps $aptOpt
endReturn -o $? "Failed to install fetchmail"
exe systemctl stop fetchmail
exe systemctl disable fetchmail
}
step_4_info() { echo "Configure postfixadmin to use fetchmail"; }
step_4() {
echo "# Create mysql config"
echo " [$PFA_SRV_LOC/fetchmail.conf]"
echo " # Follow instructions in $toolAdditionsLoc/fetchmail.pl"
echo " \$db_type = 'mysql';"
echo " \$run_dir=\"/var/lock\";"
echo
echo " [$toolAdditionsLoc/fetchmail.pl]"
echo " # Change path to fetchmail.conf (see above)"
echo
echo " [I] Run step \"timer\" when configuration is done"
}
step_6_info() {
echo "Create postfixadmin fetchmail systemd timer and reduce syslog entries"
echoinfo "Needs to start after the mysql service"
}
step_6_alias() { ALIAS="timer"; }
step_6() {
# eval needed to expand sourced configuration variables
local localService=`eval "echo \"$fetchPluginService\""`
addConf -s "$localService" "$fetchPluginServiceLoc"
addConf -s "$fetchPluginTimer" "$fetchPluginTimerLoc"
exe systemctl enable --now ${fetchPluginServiceName}.timer
addConf -s "$fetchPluginRsyslog" "$fetchPluginRsyslogLoc"
exe service rsyslog restart
}
fetchPluginServiceName="pfafetchmail"
fetchPluginServiceLoc="/etc/systemd/system/${fetchPluginServiceName}.service"
fetchPluginService="[Unit]
Description=Postfix fetchmail plugin
After=mysql.service
[Service]
# emerg (lowest log level, only highest priority messages),
# alert, crit, err, warning, notice, info, debug
LogLevelMax=notice
User=$fetchmailUser
ExecStart=\${PFA_SRV_LOC}/ADDITIONS/fetchmail.pl >>/dev/null
[Install]
WantedBy=multi-user.target"
fetchPluginTimerLoc="/etc/systemd/system/${fetchPluginServiceName}.timer"
fetchPluginTimer="[Unit]
Description=Postfix fetchmail plugin execute every minute
[Timer]
OnCalendar=minutely
Persistent=true
[Install]
WantedBy=basic.target"
fetchPluginRsyslogLoc="/etc/rsyslog.d/31-fetchmailreduce.conf"
fetchPluginRsyslog="if \$programname == 'systemd' and re_match(\$msg, \"Started.*fetchmail\") then stop
if \$programname == 'systemd' and re_match(\$msg, \"fetchmail.*Succeeded\") then stop"
step_7_info() { echo "Create separate log file for fetchmail using rsyslog"; }
step_7_alias() { ALIAS="newlog"; }
step_7() {
addConf -f "$fetchmailRsyslog" "$fetchmailRsyslogLoc"
addConf -f "$fetchmailRotate" "$fetchmailRotateLoc"
exe service rsyslog restart
}
fetchmailLogLoc="/var/log/fetchmail.log"
fetchmailRotateLoc="/etc/logrotate.d/fetchmail"
fetchmailRotate="$fetchmailLogLoc {
rotate 14
weekly
missingok
daily
compress
delaycompress
}"
fetchmailRsyslogLoc="/etc/rsyslog.d/30-fetchmail.conf"
fetchmailRsyslog="if \$programname == 'fetchmail' or \$programname == 'fetchmail-all' then $fetchmailLogLoc
& stop"
step_18_info() { echoinfoArgs "[NEW VERSION]"; echo "Check for updates"; }
step_18_alias() { ALIAS="updatecheck"; }
step_18() {
shift
local isInstalled=
local latestVersion=
if [ ! -z $1 ] ; then
latestVersion="$1"
else
latestVersion=$(curl --silent "$latestUrl" | grep -Po '"tag_name": "postfixadmin-\K.*?(?=")')
fi
isInstalled=$(grep -E "${latestVersion}" "${PFA_WEB_LOC}/version" >>/dev/null 2>&1 && echo "1" || echo "0")
if [ $isInstalled -eq 1 ] ; then
echo " [I] Version $latestVersion is already installed"
return 1
else
echo " [I] Update to $latestVersion available"
fi
return 0
}
step_20_info() {
echoinfoArgs "[POSTFIXADMIN SRV ROOT]"
echo -n "Create a backup"
if [ $CONFIG -ne 0 ] ; then
echo " at $PFA_BACKUP"
else
echo
fi
}
step_20_alias() { ALIAS="backup"; }
step_20() {
shift
local tempRoot=
if [ $CONFIG -eq 0 ] ; then
echoerr " [E] No configuration file found"
return 1
fi
if [ ! -z $PFA_BACKUP ] ; then
exe mkdir -p "$PFA_BACKUP"
fi
if [ ! -z $1 ] ; then
tempRoot="$1"
else
tempRoot="$PFA_SRV_LOC"
fi
local srvBackup="$PFA_BACKUP/${toolName}_`date +%Y%m%d-%H%M%S`.tar.gz"
echo " [I] Backing up server directory to $srvBackup"
exe cd "$tempRoot/.."
exe tar czf "$srvBackup" $(basename "$tempRoot")
exe $WDIR/mysql.sh -qq backup "$PFA_DATABASE" "$PFA_BACKUP"
}
step_22_info() {
echoinfoArgs "[CUSTOM VERSION]"
shift
if [ $CONTEXT_EXE -ne 0 ]; then
echoinfo -n "Upgrade to version "
if [ -z "$1" ]; then
echo -n "$(curl --silent "$latestUrl" | grep -Po '"tag_name": "postfixadmin-\K.*?(?=")')"
else
echo -n "$1"
fi
echo " from github"
else
echo "Upgrade to latest or a custom version from github"
fi
}
step_22_alias() { ALIAS="upgrade"; }
step_22() {
shift # don't need step number
local latestVersion=
if [ ! -z $1 ] ; then
latestVersion="$1"
else
latestVersion=$(curl --silent "$latestUrl" | grep -Po '"tag_name": "postfixadmin-\K.*?(?=")')
fi
if [ -z $latestVersion ] ; then
echoerr " [E] Cannot determine latest version from github repository"
return 1
elif [ $QUIET -eq 0 ] ; then
echo
exe read -p "Install $latestVersion to $PFA_SRV_LOC [n]o/(y)es? " answer
case $answer in
[yY])
;;
*)
echoerr " [I] Upgrade aborted"
return 1
;;
esac
fi
# Major versions are stated in the CHANGELOG.TXT without the trailing minor version e.g. "3.3" for "3.3.0"
# Trailing ".0" is removed if exists
local isInstalled=$(grep -E "Version ${latestVersion%.0} " "${PFA_SRV_LOC}/CHANGELOG.TXT" >>/dev/null 2>&1 && echo "1" || echo "0")
if [ $isInstalled -eq 1 ] ; then
echoerr " [E] Version $latestVersion is already installed"
return 2
fi
# Download
local downUrl="https://github.com/$toolName/$toolName/archive/postfixadmin-${latestVersion}.tar.gz"
local tempExtract="$tempDown/postfixadmin-postfixadmin-$latestVersion"
if [ ! -e "$tempExtract" ] ; then
exe mkdir -p "$tempDown"
exe wget -O "$tempLoc" $downUrl
endReturn -o $? "Download failed: $downUrl"
exe cd "$tempDown"
exe tar -xf "$tempLoc"
endReturn -o $? "Extract failed: $tempLoc"
else
echo " [I] Found existing download: $tempExtract"
fi
# Installation
local tempBu="${PFA_SRV_LOC}_bu_`date +%Y%m%d-%H%M%S`"
if [ -e "$PFA_SRV_LOC" ] ; then
exe mv "$PFA_SRV_LOC" "$tempBu"
step backup "$tempBu"
endReturn -o $? "Backup failed; $PFA_SRV_LOC renamed!"
fi
echo " [I] Installing version $latestVersion to $PFA_SRV_LOC"
exe cp -ar "$tempExtract" "$PFA_SRV_LOC"
exe mkdir -p $(dirname "$PFA_WEB_LOC")
echo " [I] Create symlink to $PFA_WEB_LOC"
exe ln -fs "$PFA_SRV_LOC/public" "$PFA_WEB_LOC"
# Setting file permissions
exe chown -R www-data: "$PFA_SRV_LOC/public"
# Configuration
local webConf="$tempBu/$toolConfName"
if [ -e "$webConf" ] ; then
echo " [I] Copying configuration"
exe cp -ar "$webConf" "$PFA_SRV_LOC/"
else
echo " [I] Creating empty configuration file $PFA_SRV_LOC/$toolConfName"
exep "echo -e \"# Created gy $WDIR/$(basename $0)\\n\\n# Changeme\" > \"$PFA_SRV_LOC/$toolConfName\""
fi
# Templates
local templatesLoc="$tempBu/$toolTemplates"
if [ -e "$templatesLoc" ] ; then
echo " [I] Copying $toolTemplates"
exe cp -ar "$templatesLoc" "$toolTemplatesLoc"
else
echo " [I] Creating empty directory $toolTemplatesLoc"
exe mkdir -p "$toolTemplatesLoc"
exe chown -R www-data: "$toolTemplatesLoc"
fi
exe rm -rf "$tempBu"
}
tempDown="/tmp/${toolName}"
tempLoc="$tempDown/${toolName}.tar.gz"
step_23_info() { echo "Clean temporary files: $tempDown"; }
step_23_alias() { ALIAS="clean"; }
step_23() {
exe rm -rf "$tempDown"
}
step_100_info() {
echoinfoArgs "[OPTIONS]"
echo "Execute $toolName client script"
echoinfo "[OPTIONS] are passed on to $toolName-cli unmodified"
}
step_100_alias() { ALIAS="cli"; }
step_100() {
shift
exe ${PFA_SRV_LOC}/scripts/$toolName-cli $@
}
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,3 @@
#!/bin/bash
POSTGRES_BACKUP_DIR="~/backup"

173
seqs/postgres.sh Executable file
View File

@@ -0,0 +1,173 @@
#!/bin/bash
toolName=postgres
toolDeps=postgresql
toolUser=postgres
# Needed for different steps
postgresDb=""
postgresUser=""
postgresPass=""
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="postgres.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
fi
}
step_1_info() { echo "Installing $toolName dependencies"; }
step_1_alias() { ALIAS="install"; }
step_1() {
local aptOption=
exe apt update
endReturn -o $? "Updating apt repositories failed"
if [ $QUIET -ne 0 ] ; then
aptOption="-y"
else
aptOption=""
fi
exe apt install $toolDeps $aptOption
}
step_2_info() { echo "Create postgres database"; }
step_2_alias() { ALIAS="createdb"; }
step_2() {
readDatabaseInfos
exe cd ~postgres
exe su ${toolUser} -c "psql -c \"CREATE USER ${postgresUser} WITH ENCRYPTED password '${postgresPass}';\""
exe su ${toolUser} -c "psql -c \"CREATE DATABASE ${postgresDb} ENCODING \"UTF8\" LC_COLLATE='C' LC_CTYPE='C' template=template0 OWNER ${postgresUser};\""
exe su ${toolUser} -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE \"${postgresDb}\" to ${postgresUser};\""
}
step_4_info() { echoinfoArgs "[DATABASE]"; echo "Drop a postgres database"; }
step_4_alias() { ALIAS="dropdb"; }
step_4() {
shift
local dbname=$1
if [ -z $dbname ]; then
readDatabaseInfos
dbname=$postgresDb
fi
exe cd ~postgres
exe su ${toolUser} -c "psql -c \"DROP DATABASE ${dbname};\""
}
step_6_info() { echoinfoArgs "[DATABASE]"; echo "Size of a postgres database"; }
step_6_alias() { ALIAS="sizedb"; }
step_6() {
shift
local dbname=$1
if [ -z $dbname ]; then
readDatabaseInfos
dbname=$postgresDb
fi
exe cd ~postgres
exe su ${toolUser} -c "psql -c \"SELECT pg_size_pretty( pg_database_size('$dbname') );\""
}
step_8_info() { echo "List available databases"; }
step_8_alias() { ALIAS="listdb"; }
step_8() {
exe cd ~postgres
exe su ${toolUser} -c "psql -c '\l'"
}
step_10_info() { echoinfoArgs "[DATABASE]"; echo "List all tables of a postgres database"; }
step_10_alias() { ALIAS="listtables"; }
step_10() {
shift
local dbname=$1
if [ -z $dbname ]; then
readDatabaseInfos
dbname=$postgresDb
fi
exe cd ~postgres
exe su ${toolUser} -c "psql -d $dbname -c \"\\dt\""
}
step_20_info() { echoinfoArgs "[DATABASE]"; echo "Backup ${toolName} database"; }
step_20_alias() { ALIAS="backupdb"; }
step_20() {
shift
local dbname=$1
if [ -z $dbname ]; then
readDatabaseInfos
dbname=$postgresDb
fi
#if [ ! -s ~/.pgpass ] ; then
# echo " [I] For unattended backup please define ~/.pgpass containing credentials"
# echo " e.g. localhost:5432:database:user:pass"
#fi
# -Fc custom format
#exep "pg_dump -h 127.0.0.1 -U ${postgresUser} -Fc synapse | bzip2 -c > ${toolDbBackupFolder}/`date +%Y-%m-%d\"_\"%H-%M-%S`.backup.bz2"
exe mkdir -p "$POSTGRES_BACKUP_DIR"
exe cd ~postgres
exep "su ${toolUser} -c \"pg_dump -Fc $dbname\" | bzip2 -c > ${POSTGRES_BACKUP_DIR}/`date +%Y-%m-%d\"_\"%H-%M-%S`_${dbname}.backup.bz2"
}
step_22_info() { echo "Postgres database restore"; }
step_22_alias() { ALIAS="restoredb"; }
step_22() {
echo " [I] Postgres database restore procedure"
echo "1. Create a empty postgres database first (step 4)"
echo "2. psql -h <host> -U <database user> -d <database name> -W -f <sql dump file>"
echo " e.g. psql -h 127.0.0.1 -U synapse -d synapse -W -f 2018-06-07_18-10-56.sql"
echo "or"
echo "3. Custom postgres format dump restore:"
echo " pg_restore -h localhost -p 5432 -U synapse -d new_db -v \"10.70.0.61.backup\""
echo
echo "Available postgresql databases:"
exe cd ~postgres
exe su ${toolUser} -c "psql -c '\l'"
echo "Available postgresql user:"
exe su ${toolUser} -c "psql -c '\du'"
}
step_24_info() {
local DELYEAR=$(($(date +%Y)-2))
echoinfoArgs "[DATABASE]"
echo "Clean all ${DELYEAR} backups of a database";
}
step_24_alias() { ALIAS="backupclean"; }
step_24() {
shift
local DELYEAR=$(($(date +%Y)-2))
local dbname=$1
if [ -z $dbname ]; then
readDatabaseInfos
dbname=$postgresDb
fi
exe rm -f ${POSTGRES_BACKUP_DIR}/${DELYEAR}*${dbname}*
}
# Read postgres database information dbname/user/pass if empty
readDatabaseInfos() {
if [ "$postgresDb" == "" ] ; then
read -p "Enter postgres database name: " postgresDb
endCheckEmpty postgresDb "database"
fi
if [ "$postgresUser" == "" ] ; then
read -p "Enter postgres user name: " postgresUser
endCheckEmpty postgresUser "user name"
fi
if [ "$postgresPass" == "" ] ; then
read -s -p "Enter postgres password: " postgresPass
endCheckEmpty postgresPass "password"
fi
echo
}
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

80
seqs/postgrey.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/bash
toolName=postgrey
toolDeps="$toolName"
toolWhitelistLoc="/etc/postgrey/whitelist_clients"
updateUrl="https://postgrey.schweikert.ch/pub/postgrey_whitelist_clients"
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="${toolName}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
#step_config() {
# echo "Called once before executing steps."
# ## e.g. to source a config file manually:
# #. "$CONFIG_FILE"
# ## or to use sequencer api:
# #initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
# #if [ $? -eq 0 ] ; then
# # CONFIG=1
# #fi
#}
step_1_info() { echo "Install $toolDeps"; }
step_1_alias() { ALIAS="install"; }
step_1() {
local aptOpt=
if [ $QUIET -ne 0 ];then
aptOpt="-y"
fi
exe apt update
exe apt install "$toolDeps" $aptOpt
}
step_2_info() {
echo "Add cron to update whitelist_clients from"
echoinfo "$updateUrl"
}
step_2_alias() { ALIAS="cron"; }
step_2() {
addConf -s "$postCron" "$postCronLoc"
}
postCronLoc="/etc/cron.d/postgreyWhitelistUpdate"
postCron="# -q quiet -N timestamping (overwrite existing file) -O target file
01 23 5 * * root /usr/bin/wget -qNO \"$toolWhitelistLoc\" $updateUrl && /usr/sbin/service postgrey restart"
step_3_info() { echo "Configuration notes"; }
step_3_alias() { ALIAS="notes"; }
step_3() {
echo "$toolNotes"
}
toolNotes="
# Reduce default message delay to 1 minute
[/etc/default/postgrey]
POSTGREY_OPTS=\"--inet=10023 --delay=60\"
# Custom local whitelist rules
[/etc/postgrey/whitelist_clients.local]
# Rule examples
# own domains
mydomain.com
# own network
/^.*\.(lan|local)$/
192.168.0.0/24
fd21::/64
# External domains in frequent use
# Amazon mail system
amazonses.com
"
step_10_info() { echo "Restart $toolName"; }
step_10_alias() { ALIAS="restart"; }
step_10() {
exe service $toolName restart
}
VERSION_SEQREV=11
. /usr/local/bin/sequencer.sh

5
seqs/pyload.cfg.example Normal file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
PYL_USER="pyload"
PYL_INSTALL_DIR="/opt/pyload"
PYL_CONFIG_DIR="/home/pyload"

138
seqs/pyload.sh Executable file
View File

@@ -0,0 +1,138 @@
#!/bin/bash
toolName="pyload"
toolBranch="stable"
toolDownload="https://github.com/pyload/pyload.git"
toolDeps="git liblept5 python python-crypto python-pycurl python-imaging python-sleekxmpp tesseract-ocr zip unzip python-openssl libmozjs-24-bin"
# python-cryptography shall be implemented in future releases and replace pyhton-crypto
toolDepsDebian="sudo git python-crypto python-pycurl python-pil python-sleekxmpp tesseract-ocr zip unzip pyhton-openssl libmozjs-60-dev"
toolBuildDeps="rar unrar-nonfree"
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
APTOPT=
CONFIG=0
SCRIPT_NAME=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_NAME%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
else
# End if no configuration file exists
[ $DRY -eq 0 ] && return 1
fi
[ $QUIET -ne 0 ] && APTOPT="-y"
return 0
}
step_1_info() { echo "Apt sources.list check and update"; }
step_1_alias() { ALIAS="install"; }
step_1() {
echo "Make sure you have the \"deb-src\" entry active in your /etc/apt/sources.list"
echo "Especially check for \"non-free\""
exe read -p "Press Enter to continue: "
exe vi /etc/apt/sources.list
exe apt update
}
step_2_info() { echo "Install unrar-nonfree from source"; }
step_2() {
exe apt-get build-dep ${toolBuildDeps} $APTOPT
exe cd /tmp
exe apt-get source -b unrar-nonfree
saveReturn $?
endReturn
exe dpkg -i unrar_*_armhf.deb
exe rm -rf unrar-*
}
step_3_info() {
echoinfoArgs "[TARGET]"
echo "Install dependencies"
echoinfo " [TARGET] (default: raspi)"
echoinfo " raspi: Raspberry Pi OS"
echoinfo " debian: Debian"
}
step_3_alias() { ALIAS="deps"; }
step_3() {
shift
local lDeps="$toolDeps"
case "$1" in
debian)
lDeps="$toolDepsDebian";;
raspi);;
*)
echoerr " [E] Unrecognized target"
return 1;;
esac
exe apt-get install ${lDeps} $APTOPT
saveReturn $?
endReturn
case "$1" in
raspi)
exe cd /usr/bin
exe ln -s js24 js;;
debian)
exe cd /usr/bin
exe ln -s js60 js;;
esac
}
step_4_info() { echo "Get $toolName from $toolDownload and create dedicated user"; }
step_4() {
exe git clone -b $toolBranch $toolDownload "$PYL_INSTALL_DIR"
endReturn -o $? "Git clone failed"
exe adduser --system --home "$PYL_CONFIG_DIR" "$PYL_USER"
}
step_5_info() { echo "Make initial configuration"; }
step_5() {
echo "Webinterface server \"threaded\" is recommended on a raspberry pi."
exe read -p "Press Enter to continue: "
exe cd "$PYL_INSTALL_DIR"
exe sudo -u $PYL_USER python pyLoadCore.py
}
step_6_info() { echo "Create systemd service"; }
step_6() {
local lService=`eval "echo \"$toolService\""`
addConf -c "$lService" "$toolServiceLoc"
}
toolServiceLoc="/etc/systemd/system/pyload.service"
toolService="[Unit]
Description=Python Downloader
After=network.target
[Service]
User=pyload
ExecStart=/usr/bin/python \${PYL_INSTALL_DIR}/pyLoadCore.py
[Install]
WantedBy=multi-user.target"
step_7_info() { echo "Add ufw rules"; }
step_7_alias() { ALIAS="ufw"; }
step_7() {
echoseq " [I] Port 9666 needs to be forwarded to the target machine with ssh"
echoseq " ssh -L 9666:localhost:9666 user@host -N"
exe ufw allow in on eth0 to any port 8000 proto tcp comment "pyload webinterface"
exe ufw allow in on eth0 to any port 7227 proto tcp comment "pyload remotes"
exe ufw allow out on eth0 to 192.168.23.20 port 5222 proto tcp comment "XMPP Connection"
}
step_10_info() { echo "Upgrade to latest version of branch $toolBranch"; }
step_10_alias() { ALIAS="upgrade"; }
step_10() {
exe service $toolName stop
exe cd "$PYL_INSTALL_DIR"
exe git pull
echo " [I] Service is not started automatically"
echo " Do so manually with: service $toolName start"
}
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

618
seqs/raspberry.sh Executable file
View File

@@ -0,0 +1,618 @@
#!/bin/bash
# Collection of setup steps for a new raspberry pi
# (e.g. boot from HD, disable swap file, ...)
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
#CONFIG_FILE="$WDIR/${toolName}.cfg"
#CONFIG_FILE_DEFAULT="${CONFIG_FILE}.example"
osName=
distName=
RPI_BOOT_CONFIG="/boot/config.txt"
step_config() {
# Shift away args
local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
# Set download url with specified CPU architecture
PIDOWNURL="https://downloads.raspberrypi.org/raspios_lite_${PIARCH}_latest"
if [ "$(which lsb_release)" == "" ] ; then
echoerr " [W] Cannot detect OS. Assuming Ubuntu"
osName="Ubuntu"
else
osName=$(lsb_release -is)
distName=$(lsb_release -cs)
fi
if [ "$osName" == "" ] ; then
echoerr " [W] Error dedecting OS. Assuming Ubuntu"
osName="Ubuntu"
fi
echoseq " Detected OS: $osName $distName"
echoseq " Requested CPU Architecture: $PIARCH"
return 0
}
PIARCH=armhf
PIDOWNURL=
SDDEV=
SDBOOT=
SDBOOTPUUID=
SDROOT=
SDROOTDEV=
SDROOTPUUID=
HDDEV=
HDROOT=
HDROOTPUUID=
HDSWAP=
HDSWAPPUUID=
evalArgs() {
local argCount=0
for arg in "$@"; do
case "$1" in
-a|--arch)
if [ ! -z "$2" ]; then
PIARCH="$2"
((argCount+=2))
else
((argCount+=1))
fi
shift $argCount
;;
*)
break
;;
esac
done
return $argCount
}
step_1_info() {
# Shift away args
shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
echoinfoArgs "[OPTIONS] [SD CARD DEVICE] [HD DEVICE]"
echo "Download latest Raspberry Pi OS lite image $PIARCH"
if [ $CONTEXT_EXE -ne 0 ]; then
echoinfo "Download URL: $PIDOWNURL"
else
echoinfo " [OPTIONS]"
echoinfo " -a, --arch : armhf (default), arm64"
fi
}
step_1_alias() { ALIAS="setup"; }
step_1() {
# Shift away args
shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
if [ ! -f "$downLoc" ] ; then
exe wget "$PIDOWNURL" -O "$downLoc"
echo -ne " [I] sha256 sum of download:\n "
exe sha256sum "$downLoc"
fi
downImgName="${downDir}/$(zipinfo -1 "$downLoc")"
if [ ! -f "$downImgName" ] ; then
exe unzip "$downLoc" -d "$downDir"
endReturn -o $? "Unzip raspios image $PIARCH failed"
fi
}
downImgName=""
downDay=$(date +%Y%m%d)
downDir="/tmp"
downLoc="${downDir}/raspios_$downDay.zip"
step_2_info() {
# Shift away args
shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
echoinfoArgs "[OPTIONS] [SD CARD DEVICE]"
echo "Write Raspberry Pi OS image to SD card"
echoinfo "This operation will delete all data previously on the SD card!"
[ $CONTEXT_EXE -ne 0 ] && [ ! -z $1 ] && echoinfo " [SD CARD DEVICE]: $1"
}
step_2_alias() { ALIAS="writesd"; }
step_2() {
# Shift away args
shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
if [ "$downImgName" == "" ] ; then
# called again to make sure $downImgName is populated
step setup
fi
if [ ! -f "$downImgName" ] ; then
endReturn -o 1 "No raspios image found"
fi
if [ $(id -u) -ne 0 ] ; then
endReturn -o 1 "No root"
fi
read_sd_dev "$1"
# check if device was confirmed
if [ $? -ne 0 ] ; then
endReturn -o 1 "SD card device not found"
fi
# write image
exe dd bs=8M if="$downImgName" of="$SDDEV" conv=fsync
endReturn -o "$?" "Writing image to $SDDEV failed"
exe sync
# SD partitions will have new informations now
# Leave SD card device intact for next step
SDBOOT=""
SDROOT=""
# TODO ? automatic remount
echoerr " [W] Please remove SD now and plug it back in."
exe read -p " Press enter to contiue."
}
step_3_info() {
# Shift away args
shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
echoinfoArgs "[SD CARD DEVICE]"
echo "Prepare SD for first run"
if [ $CONTEXT_EXE -ne 0 ]; then
[ ! -z $1 ] && echoinfo " [SD CARD DEVICE]: $1"
fi
}
step_3() {
# Shift away args
shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
if [ -z $1 ] && [ ! -z $SDDEV ] ; then
if [ $QUIET -ne 0 ] ; then
answer="n"
else
exe lsblk -p "$SDDEV"
echo
exe read -p "Is $SDDEV still the SD card (y/[n])? " answer
fi
case $answer in
[yY])
# Nothing todo
;;
*)
SDDEV=""
;;
esac
fi
read_sd_dev "$1"
endReturn -o $? "SD card device not found"
if [ ! -w "$SDBOOT" ] ; then
echoerr " [E] SD card boot partion not writeable"
return 1
fi
# enable systemd ssh service
echo " [I] Enable SSH access"
exe touch "$SDBOOT"/ssh
# save SD boot settings for easy emergency start from SD
echo " [I] Save SD card boot information for later use"
exe cp -ar "$SDBOOT"/cmdline.txt "$SDBOOT"/cmdline.txt.sd
exe cp -ar "$SDROOT"/etc/fstab "$SDROOT"/etc/fstab.sd
}
step_4_info() {
# Shift away args
shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
echoinfoArgs "[SD CARD DEVICE] [HD DEVICE]"
echo "Prepare SD card to boot from hard disk"
if [ $CONTEXT_EXE -ne 0 ]; then
[ ! -z $1 ] && echoinfo " [SD CARD DEVICE]: $1"
[ ! -z $2 ] && echoinfo " [HD DEVICE]: $2"
fi
}
step_4_alias() { ALIAS="hdboot"; }
step_4() {
# Shift away args
shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
read_sd_dev "$1"
endReturn -o $? "SD detection error $?"
read_hd_dev "$2"
endReturn -o $? "HD detection error"
echo " [I] SD: $SDDEV"
echo " $SDBOOT [$SDBOOTPUUID]"
echo " $SDROOT [$SDROOTPUUID]"
echo " [I] HD: $HDDEV"
echo " $HDROOT [$HDROOTPUUID]"
echo " $HDSWAP [$HDSWAPPUUID]"
echo
# Point boot command line to SSD
echo -n " [I] modify PARTUUID of $SDBOOT/cmdline.txt"
if [ ! -z $HDROOTPUUID ] ; then
exe sed -i -E "s/root=PARTUUID=[a-f0-9-]+/root=PARTUUID=${HDROOTPUUID}/" "$SDBOOT/cmdline.txt"
if [ $? -eq 0 ] ; then
echo " ... Ok"
else
echo -e "\n Failed! Replace PARTUUID manually"
fi
else
echo " Replace \"root=PARTUUID=******00-01\" manually"
fi
# Disable initial resizing of the second partition
echo -n " [I] remove \"init=/usr/lib/raspi-config/init_resize.sh\""
exe sed -i -E "s/[ ]*init=.*\/init_resize\.sh//" "$SDBOOT/cmdline.txt"
if [ $? -eq 0 ] ; then
echo " ... Ok"
else
echo -e "\n Failed! Remove init=... manually"
fi
# Save modifications for HD boot
exe cp -ar "$SDBOOT"/cmdline.txt "$SDBOOT"/cmdline.txt.hd
echo
# Resize second partition of SD to max. possible size
echo " [I] Resize root partion of SD: ${SDROOT} "
step resizesd "$SDDEV"
if [ $? -ne 0 ] ; then
echoerr " [W] Something seems to have failed during resize"
else
# Disable init script to resize SD
echo -n " [I] remove \"init=\" part from $SDBOOT/cmdline.txt.sd"
exe sed -i -E "s/[ ]*init=.*\/init_resize\.sh//" "$SDBOOT/cmdline.txt.sd"
if [ $? -eq 0 ] ; then
echo " ... Ok"
else
echo -e "\n Failed! Remove init=... manually"
fi
fi
}
step_5_info() {
# Shift away args
shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
echoinfoArgs "[SD CARD DEVICE] [HD DEVICE]"
echo "Prepare HD for boot (TODO)"
if [ $CONTEXT_EXE -ne 0 ]; then
[ ! -z $1 ] && echoinfo " [SD CARD DEVICE]: $1"
[ ! -z $2 ] && echoinfo " [HD DEVICE]: $2"
fi
}
step_5() {
# Shift away args
shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $?
#TODO
echoerr " [E] Not ready yet...TODO"
#return 1
read_sd_dev "$1"
endReturn -o $? "SD detection error $?"
read_hd_dev "$2"
endReturn -o $? "HD detection error"
echo " [I] SD: $SDDEV"
echo " $SDBOOT [$SDBOOTPUUID]"
echo " $SDROOT [$SDROOTPUUID]"
echo " [I] HD: $HDDEV"
echo " $HDROOT [$HDROOTPUUID]"
echo " $HDSWAP [$HDSWAPPUUID]"
echo
# TODO how to partition HD
echo " [I] $HDDEV is expected to be partitioned with root and swap"
echo " TODO create a step for partitioning script support?!"
echo
# Initial rsync of system to HD
echo " [I] Clone SD root to HD root:"
echo " rsync -avxHAX --numeric-ids --info=stats2 $SDROOT/ $HDROOT/"
echo
# Modify fstab on HD for root and swap on HD
echo " [I] modify $HDROOT/etc/fstab"
echo " PARTUUID=$SDBOOTPUUID /boot vfat ro,defaults 0 2"
echo " PARTUUID=$SDROOTPUUID /backup ext4 ro,defaults,noatime 0 2"
echo " PARTUUID=$HDROOTPUUID / ext4 defaults,noatime 0 1"
echo " PARTUUID=$HDSWAPPUUID none swap sw 0 0"
echo
# etc
echo " [I] modify $HDROOT/etc/dhcpcd.conf for static IPs"
}
read_sd_dev() {
local partExt=""
if [ ! -z "$1" ] ; then
SDBOOT=
SDROOT=
SDROOTDEV=
SDROOTPUUID=
SDBOOTPUUID=
SDDEV="$1"
elif [ -z $SDDEV ] || [ ! -b "$SDDEV" ] ; then
SDDEV=
SDBOOT=
SDROOT=
SDROOTDEV=
SDBOOTPUUID=
SDROOTPUUID=
echo " [I] Available devices:"
echo
exe lsblk -p
echo
exe read -p "Provide SD card device (e.g. /dev/sdb): " SDDEV
fi
if [ ! -b "$SDDEV" ] ; then
echoerr " [I] $SDDEV not a block device"
SDDEV=
return 1
fi
if [[ "$SDDEV" =~ .*blk.* ]] ; then
partExt="p"
fi
if [ -z $SDBOOT ] ; then
SDBOOT=$(findmnt -no TARGET "${SDDEV}${partExt}${SDBOOTPARTNO}")
fi
if [ -z $SDBOOTPUUID ] ; then
IFS=\" read -r _ vPARTUUID _ < <(blkid "${SDDEV}${partExt}${SDBOOTPARTNO}" -s PARTUUID)
SDBOOTPUUID=$vPARTUUID
fi
SDROOTDEV=${SDDEV}${partExt}${SDROOTPARTNO}
if [ -z $SDROOT ] ; then
SDROOT=$(findmnt -no TARGET "${SDROOTDEV}")
fi
if [ -z $SDROOTPUUID ] ; then
SDROOTPUUID=$(findmnt -no PARTUUID "${SDROOTDEV}")
fi
return 0
}
SDBOOTPARTNO=1
SDROOTPARTNO=2
read_hd_dev() {
if [ ! -z "$1" ] ; then
HDROOT=
HDROOTPUUID=
HDSWAPPUUID=
HDDEV="$1"
elif [ -z $HDDEV ] || [ ! -b "$HDDEV" ] ; then
HDROOT=
HDROOTPUUID=
HDSWAPPUUID=
echo " [I] Available devices:"
echo
exe lsblk -p
echo
exe read -p "Provide HD device (e.g. /dev/sdf): " HDDEV
fi
if [ ! -b "$HDDEV" ] ; then
HDDEV=
return 1
fi
if [ -z $HDROOT ] ; then
HDROOT=$(findmnt -no TARGET "${HDDEV}1")
fi
if [ -z $HDROOTPUUID ] ; then
IFS=\" read -r _ vPARTUUID _ < <(blkid "${HDDEV}1" -s PARTUUID)
HDROOTPUUID=$vPARTUUID
fi
if [ -z $HDSWAPPUUID ] ; then
IFS=\" read -r _ vPARTUUID _ < <(blkid "${HDDEV}2" -s PARTUUID)
HDSWAPPUUID=$vPARTUUID
HDSWAP="${HDDEV}2"
fi
return 0
}
step_20_info() { echo "Disable swap file and remove it"; }
step_20_alias() { ALIAS="disable_swap"; }
step_20() {
exe swapoff -a
exe systemctl disable dphys-swapfile
exe rm -rf "$rpiSwapFile"
echoerr " [W] Reboot to apply changes"
if [ $QUIET -eq 0 ] ; then
exe read -p " Reboot now ([n]/y)? " answer
case $answer in
[yY])
echoerr " [I] Rebooting now ..."
exe reboot
;;
*)
;;
esac
fi
}
rpiSwapFile="/var/swap"
step_22_info() { echoinfoArgs "[SD CARD DEVICE]"; echo "Resize second SD card partition"; }
step_22_alias() { ALIAS="resizesd"; }
step_22() {
shift
read_sd_dev "$1"
if [ -z $SDDEV ] || [ "$SDDEV" = "" ] || [ "$SDROOT" == "/" ] ; then
echoerr " [E] No SD found"
return 1
fi
echo " [I] Device to be resized: $SDROOTDEV"
exe umount -q "$SDROOT"
exe parted -s "$SDDEV" "resizepart $SDROOTPARTNO -1" quit
saveReturn $?
exe e2fsck -f "$SDROOTDEV"
saveReturn $?
exe resize2fs "$SDROOTDEV"
saveReturn $?
if [ -z $SDROOT ] ; then
read -p "Please provide a mountpoint: " SDROOT
exe mkdir -p "$SDROOT"
fi
exe mount "$SDROOTDEV" "$SDROOT"
saveReturn $?
getReturn
return $?
}
step_24_info() {
echoinfoArgs "[OPTION]"
echo "Turn off power LED"
echoinfo " [OPTION]"
echoinfo " -p : Turn off permanentely (/etc/rc.local)"
}
step_24_alias() { ALIAS="disable_powerled"; }
step_24() {
exep "${ledOffCmd}"
if [ ! -z "$2" ] && [ "$2" == "-p" ] ; then
exep "grep \"$ledPowerBright\" $startScript >>/dev/null"
if [ $? -eq 0 ] ; then
echo " [I] Power LED brightness already used. Please check $startScript manually for:"
echo " $ledOffCmd"
return 1
fi
exe sed -i "s/^exit 0/# Turn off power LED/" "$startScript"
exep "echo \"${ledOffCmd}\" >> $startScript"
exep "echo -e \"\nexit 0\" >> $startScript"
fi
}
startScript="/etc/rc.local"
ledPowerBright="/sys/class/leds/led1/brightness"
ledOffCmd="sudo sh -c 'echo 0 > ${ledPowerBright}'"
step_26_info() { echo "Restart network without reboot"; }
step_26_alias() { ALIAS="netrestart"; }
step_26() {
exep "sudo ip link set eth0 down && sudo ip link set eth0 up"
}
step_28_info() { echo "Disable bluetooth"; }
step_28_alias() { ALIAS="disable_bluetooth"; }
step_28() {
checkBootConfig "$RPI_CONFIG_DTOVERLAY" "$RPI_CONF_DI_BLUETOOTH"
[ $? -eq 0 ] && endReturn -o 1 "Bluetooth already disabled"
addConf -a "${RPI_CONFIG_DTOVERLAY}=$RPI_CONF_DI_BLUETOOTH" "$RPI_BOOT_CONFIG"
}
RPI_CONFIG_DTOVERLAY="dtoverlay"
RPI_CONF_DI_BLUETOOTH="disable-bt"
RPI_CONF_DI_WIFI="disable-wifi"
step_29_info() { echo "Disable bluetooth services"; }
step_29() {
exe systemctl disable hciuart.service
exe systemctl disable bluealsa.service
exe systemctl disable bluetooth.service
echoseq " [I] Consider uninstalling bluetooth software:"
echoseq "apt purge --autoremove -y bluez"
echoseq
echoseq " [W] Reboot to make changes active"
}
step_31_info() { echo "Disable Wifi"; }
step_31_alias() { ALIAS="disable_wifi"; }
step_31() {
checkBootConfig "$RPI_CONFIG_DTOVERLAY" "$RPI_CONF_DI_WIFI"
[ $? -eq 0 ] && endReturn -o 1 "Wifi already disabled"
addConf -a "${RPI_CONFIG_DTOVERLAY}=$RPI_CONF_DI_WIFI" "$RPI_BOOT_CONFIG"
echoseq " [W] Reboot to make changes active"
}
step_33_info() { echo "Disable HDMI"; }
step_33_alias() { ALIAS="disable_hdmi"; }
step_33() {
checkBootConfig "$RPI_CONFIG_HDMI_BLANK" "$RPI_CONF_DI_HDMI"
[ $? -eq 0 ] && endReturn -o 1 "HDMI already disabled"
addConf -a "${RPI_CONFIG_HDMI_BLANK}=$RPI_CONF_DI_HDMI" "$RPI_BOOT_CONFIG"
}
RPI_CONFIG_HDMI_BLANK="hdmi_blanking"
RPI_CONF_DI_HDMI="1"
step_34_info() { echo "Disable TV service"; }
step_34() {
exe $tvserviceOffCmd
exep "grep \"$tvserviceBin\" $startScript >>/dev/null"
if [ $? -eq 0 ] ; then
echo " [I] Tvservice already used. Please check $startScript manually for:"
echo " $tvserviceOffCmd"
return 1
fi
exe sed -i "s/^exit 0/# Turn off tvservice/" "$startScript"
exep "echo \"${tvserviceOffCmd}\" >> $startScript"
exep "echo -e \"\nexit 0\" >> $startScript"
echoseq " [W] Reboot to make changes active"
}
tvserviceBin="/usr/bin/tvservice"
tvserviceOffCmd="${tvserviceBin} -o'"
# checkBootConfig <CONFIGNAME> [VALUE]
checkBootConfig() {
[ -z "$1" ] && return 1
local re_check="^[[:blank:]]*[^#]*${1}[[:blank:]]*=[[:blank:]]*$2"
grep -rqE "$re_check" "$RPI_BOOT_CONFIG"
return $?
}
step_100_alias() { ALIAS="notes"; }
step_100() {
outColor green
cat <<NOTES_EOF
# Initial configuration steps
* Set password for pi (\`passwd\`)
* Add [\$HOME/.ssh/authorized_keys]
* Set hostname (\`raspi-config\` -> System Options))
* Configure Timezone (\`raspi-confg\` -> Localisation Options)
* Set GPU memory (\`raspi-config\` -> Performance Options)
* Configure swap partition
[/etc/fstab]
> \`PARTUUID=******-03 none swap sw 0 0\`
\`$SEQ_NAME disable_swap\`
* Update system
\`apt update && apt dist-upgrade\`
* Configure own NTP server
[/etc/systemd/timesyncd.conf]
> NTP=<NTP server IP>
\`system systemd-timesyncd restart\`
* Configure vim to remember last position in a file
Uncomment the following in [/etc/vim/vimrc]
> \`au BufReadPost ...\`
NOTES_EOF
}
VERSION_SEQREV=15
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,3 @@
proc /proc proc defaults 0 0
PARTUUID=mysdid-boot /boot vfat ro,defaults 0 2
PARTUUID=mysdid-backup /backup ext4 ro,defaults,noatime 0 2

4
seqs/redis.cfg.example Normal file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
# If you use a password you may set it here for cli commands
REDIS_AUTH=

86
seqs/redis.sh Executable file
View File

@@ -0,0 +1,86 @@
#!/bin/bash
toolName=redis
toolDeps=redis-server
# Get script working directory
# (when called from a different directory)
WDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >>/dev/null 2>&1 && pwd)"
CONFIG=0
SCRIPT_NAME=$(basename -- $0)
SCRIPT_NAME=${SCRIPT_NAME%%.*}
CONFIG_FILE_NAME="${SCRIPT_NAME}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
initSeqConfig "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $? -eq 0 ] ; then
CONFIG=1
fi
}
step_1_info() { echo "Install $toolName"; }
step_1_alias() { ALIAS="install"; }
step_1() {
local aptOpt=
if [ $QUIET -ne 0 ];then
aptOpt="-y"
fi
exe apt update
exe apt install $toolDeps $aptOpt
}
step_2_info() { echo "Installation notes"; }
step_2_alias() { ALIAS="notes"; }
step_2() {
cat <<NOTES_EOF
# For php applications make sure php-redis is installed
apt install php-redis
# Bind to localhsot
[/etc/redis/redis.conf]
bind 127.0.0.1 ::1
# or use socket
unixsocket /var/run/redis/redis-server.sock
unixsocketperm 770
## Password protect
requirepass verystrongpassword
# Nextcloud configuration
[/var/www/nextcloud/config/config.php]
'memcache.locking' => '\\OC\\Memcache\\Redis',
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'redis' =>
array (
'host' => '/var/run/redis/redis-server.sock',
'port' => 0,
'password' => 'verystrongpassword',
'timeout' => 0.0,
),
NOTES_EOF
}
step_10_info() {
echoinfoArgs "[CLI COMMAND]"
echo "Execute redis-cli commands"
echoinfo " [CLI COMMAND]"
echoinfo " e.g. info"
}
step_10_alias() { ALIAS="cli"; }
step_10() {
shift
local cliCmd="$@"
if [ ! -z "$REDIS_AUTH" ] ; then
#exe "echo -e \"AUTH=$REDIS_AUTH$cliCmd\" | redis-cli"
exe redis-cli -a "$REDIS_AUTH" $cliCmd
else
exe redis-cli $cliCmd
fi
}
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1,8 @@
#!/bin/bash
# Roundcube sequence configuration
# RC = RoundCube
RC_LOC="/var/www/webmail"
RC_BACKUP="/root/backup/roundcube"
RC_DATABASE="roundcube_db"

258
seqs/roundcube.sh Executable file
View File

@@ -0,0 +1,258 @@
#!/bin/bash
toolName=roundcube
toolPhpDeps="php\${phpVersion}-gd php-imagick"
#https://github.com/roundcube/roundcubemail/releases/latest
latestUrl="https://api.github.com/repos/roundcube/roundcubemail/releases/latest"
latestVersion=
tempExtract=
tempInstall=
phpVersion=
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG=0
CONFIG_FILE_NAME="${toolName}.cfg"
CONFIG_FILE_TEMPLATE="$WDIR/${CONFIG_FILE_NAME}.example"
step_config() {
## use sequencer api:
initSeqConfig -t "$CONFIG_FILE_NAME" "$CONFIG_FILE_TEMPLATE"
if [ $CONFIG -eq 0 ] ; then
CONFIG=1
fi
}
step_1_info() { echo "Install $toolName"; }
step_1_alias() { ALIAS="install"; }
step_1() {
local aptOpt=
if [ $QUIET -ne 0 ];then
aptOpt="-y"
fi
downloadLatest
fetchPhpVersion
if [ ! -z $phpVersion ] ; then
exe apt update
exe apt install `eval echo "$toolPhpDeps"` $aptOpt
fi
exe chown -R www-data: "$tempExtract"
exe cp -nar "$tempExtract" "$RC_LOC"
}
step_2_info() { echo "Install composer"; }
step_2() {
exe cd "$RC_LOC"
local EXPECTED_CHECKSUM="$(wget -q -O - https://composer.github.io/installer.sig)"
exe php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
local ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
then
echoerr ' [E] Invalid installer checksum'
exe rm composer-setup.php
return 1
fi
exe php composer-setup.php --quiet
saveReturn $?
exe rm composer-setup.php
endReturn "Composer setup failed"
}
step_3_info() { echo "Configure $toolName"; }
step_3_alias() { ALIAS="config"; }
step_3() {
echo " [I] Recommended composer packages to be added to \"require\" section:"
echo ' "melanie2/mobile": "*",'
echo ' "roundcube/carddav": "*",'
echo ' "alexandregz/twofactor_gauthenticator": "dev-master"'
exe read -p "Copy the lines above and press Enter to continue."
exe vi "$RC_LOC/composer.json"
step postupgrade
echo " [I] Generating mysql database $RC_DATABASE"
echo
exe $WDIR/mysql.sh createdb -c utf8mb4
echo
echo " [I] Now visit: http://url-to-roundcube/installer/"
echo
echo " ! Check the database password in $RC_LOC/config/config.inc.php"
echo " afterwards, the installer may have corrupted some special character"
echo
echo " ! After installation please delete $RC_LOC/installer"
}
step_10_info() { echo "Configuration notes"; }
step_10_alias() { ALIAS="notes"; }
step_10() {
outColor green
cat <<NOTES_END
# smtp port if missing after installation
[$RC_LOC/config/config.inc.php]
// SMTP port (default is 25; use 587 for STARTTLS or 465 for the
// deprecated SSL over SMTP (aka SMTPS))
\$config['smtp_port'] = 465;
# Enable two factor auth (installed with step config) for all user
[$RC_LOC/plugins/twofactor_gauthenticator/config.inc.php]
$rcmail_config['users_allowed_2FA'] = array('.*');
# Add mobile skin to roundcube and run step 'postupgrade'.
Don't forget to activate plugins if asked for.
[$RC_LOC/composer.json]
"require": {
...
"mobiledetect/mobiledetectlib": "^2.8",
"roundcube/elastic4mobile": "dev-master"
}
# Install pspell and aspell spell check engine
apt install php7.x-pspell aspell-en aspell-de
[$RC_LOC/config/config.inc.php]
\$config['spellcheck_engine'] = 'pspell';
\$config['spellcheck_languages'] = array(
'en' => 'English',
'de' => 'Deutsch',
);
NOTES_END
}
step_12_info() { echo "Troubleshooting"; }
step_12_alias() { ALIAS="trouble"; }
step_12() {
outColor green
cat <<TROUBLE_END
# On composer update errors.
* Backup '/var/www/webmail/plugin' config. Especially twofactor_gauthenticator
* Delete '/var/www/webmail/vendor' folder. Or at least 'vendor/autoload.php' and 'vendor/composer'
* 'sqn_roundcube -q postupgrade'
I also installed 'php-pear' since one error indicated connection to it.
TROUBLE_END
}
step_20_info() {
echo -n "Create a backup"
if [ $CONFIG -ne 0 ] ; then
echo " at $RC_BACKUP"
else
echo
fi
}
step_20_alias() { ALIAS="backup"; }
step_20() {
if [ $CONFIG -eq 0 ] ; then
echoerr " [E] No configuration file found"
return 1
fi
if [ ! -z $RC_BACKUP ] ; then
exe mkdir -p "$RC_BACKUP"
fi
exe $WDIR/mysql.sh -qq backup "$RC_DATABASE" "$RC_BACKUP"
local wwwBackup="$RC_BACKUP/${toolName}_www_`date +%Y%m%d-%H%M%S`.tar.gz"
echo " [I] Backing up webserver directory to $wwwBackup"
exe cd "$RC_LOC/.."
exe tar czf "$wwwBackup" $(basename "$RC_LOC")
}
step_22_info() {
echoinfoArgs "[CUSTOM VERSION]"
echo "Upgrade installation to \"latest\" from github if [CUSTOM_VERSION] is empty"
}
step_22_alias() { ALIAS="upgrade"; }
step_22() {
shift # don't need step number
local currentVersion=
if [ ! -z $1 ] ; then
latestVersion="$1"
else
fetchLatestVersion
fi
if [ -z $latestVersion ] ; then
echoerr " [E] Cannot determine latest version from github repository"
return 1
elif [ $QUIET -eq 0 ] ; then
echo
currentVersion="$(grep -Po ' \| Version \K.*?(?= )' $RC_LOC/index.php)"
exe read -p "Install $latestVersion over $currentVersion to $RC_LOC [n]o/(y)es? " answer
case $answer in
[yY])
;;
*)
echoerr " [I] Upgrade aborted"
return 1
;;
esac
fi
local isInstalled=$(grep -E "RELEASE $latestVersion" "${RC_LOC}/CHANGELOG" >>/dev/null && echo "1" || echo "0")
if [ $isInstalled -eq 1 ] ; then
echoerr " [E] Version $latestVersion is already installed"
return 2
fi
downloadLatest
step backup
echo " [I] Installing version $latestVersion to $RC_LOC"
exe "$tempInstall" "$RC_LOC"
echo " [I] Make sure to check composer.json-dist file for upstream changes"
}
step_23_info() { echo "Post upgrade procedure"; }
step_23_alias() { ALIAS="postupgrade"; }
step_23() {
exe cd "$RC_LOC"
echo " [I] Starting post update procedure"
exe php composer.phar update --no-dev
}
fetchPhpVersion() {
if [ ! -z $phpVersion ] ; then
return 0
fi
phpVersion="$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')"
}
fetchLatestVersion() {
if [ ! -z $latestVersion ] ; then
return 0
fi
latestVersion=$(curl --silent "$latestUrl" | grep -Po '"tag_name": "\K.*?(?=")')
}
downloadLatest() {
fetchLatestVersion
local downUrl="https://github.com/roundcube/roundcubemail/releases/download/${latestVersion}/roundcubemail-${latestVersion}-complete.tar.gz"
tempExtract="$tempDown/roundcubemail-$latestVersion"
tempInstall="$tempExtract/bin/installto.sh"
if [ ! -e "$tempExtract" ] ; then
exe mkdir -p "$tempDown"
exe wget -O "$tempLoc" $downUrl
endReturn -o $? "Download failed: $downUrl"
exe cd "$tempDown"
exe tar -xf "$tempLoc"
endReturn -o $? "Extract failed: $tempLoc"
else
echo " [I] Found existing download: $tempExtract"
fi
}
tempDown="/tmp/roundcube"
tempLoc="$tempDown/rc.tar.gz"
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

110
seqs/rsyslog.sh Executable file
View File

@@ -0,0 +1,110 @@
#!/bin/bash
# rsyslog management
#
# source:
# - https://selivan.github.io/2017/02/07/rsyslog-log-forward-save-filename-handle-multi-line-failover.html
toolName="rsyslog"
toolConfig="/etc/rsyslog.conf"
# Get script working directory
# (when called from a different directory)
WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )"
CONFIG_SNMP="$WDIR/${toolName}/10-snmp.conf"
CONFIG_CRON="$WDIR/${toolName}/10-cron.conf"
CONFIG_RNGD="$WDIR/${toolName}/10-rngd.conf"
CONFIG_REMOTE="$WDIR/${toolName}/90-remote.conf"
step_1_info() { echo "Install $toolName"; }
step_1_alias() { ALIAS="install"; }
step_1() {
exe apt update
exe apt install "$toolName"
}
step_2_info() { echo "Check configuration"; }
step_2_alias() { ALIAS="checkconf"; }
step_2() {
exe rsyslogd -N 1 -f "$toolConfig"
endReturn -o $? "Invalid $toolName configuration"
}
step_10_info() { echo "Reduce snmpd syslog messages"; }
step_10_alias() { ALIAS="snmpd"; }
step_10() {
addConf -s -f "$CONFIG_SNMP" "$CONFIG_SNMP_DEST"
endReturn -o $?
step checkconf
exe service rsyslog restart
}
CONFIG_SNMP_DEST="/etc/rsyslog.d/$(basename $CONFIG_SNMP)"
step_12_info() { echo "Reduce cron syslog messages"; }
step_12_alias() { ALIAS="cron"; }
step_12() {
addConf -s -f "$CONFIG_CRON" "$CONFIG_CRON_DEST"
endReturn -o $?
step checkconf
exe service rsyslog restart
}
CONFIG_CRON_DEST="/etc/rsyslog.d/$(basename $CONFIG_CRON)"
step_14_info() { echo "Reduce rngd syslog messages"; }
step_14_alias() { ALIAS="rngd"; }
step_14() {
addConf -s -f "$CONFIG_RNGD" "$CONFIG_RNGD_DEST"
endReturn -o $?
step checkconf
exe service rsyslog restart
}
CONFIG_RNGD_DEST="/etc/rsyslog.d/$(basename $CONFIG_RNGD)"
step_16_info() {
echoinfoArgs "<REMOTE_IP:PORT>"
echo "Send syslog messages to remote syslog server"
}
step_16_alias() { ALIAS="remote"; }
step_16() {
local rex='^[0-9\.]+\:[0-9]+$'
local remoteHost=""
# Check if string is a ipv4 address and port
if [[ "$2" =~ $rex ]] ; then
remoteHost=$2
else
echoerr " [E] No valid IP:PORT detected: $2"
return 1
fi
addConf -s -f "$CONFIG_REMOTE" "$CONFIG_REMOTE_DEST"
endReturn -o $? "Custom remote host $remoteHost not applied to destination or $MISSING_CONF"
exe sed -i "s/12\.34\.56\.78\:514/${remoteHost}/" "$CONFIG_REMOTE_DEST"
endReturn -o $? "Couldn't apply $remoteHost to $CONFIG_REMOTE_DEST"
step checkconf
exe service rsyslog restart
}
CONFIG_REMOTE_DEST="/etc/rsyslog.d/$(basename $CONFIG_REMOTE)"
step_17_info() { echo "Add ufw rules for sending to remote syslog. Port 514/tcp"; }
step_17_alias() { ALIAS="ufw"; }
step_17() {
exe ufw allow out on eth0 to any port 514 proto tcp comment "syslog remote"
}
step_30_info() { echo "Activating syslog server"; }
step_30_alias() { ALIAS="server"; }
step_30() {
outColor green
cat << SERVER_EOF
# Uncomment the chapter
provide UDP syslog reception
provide TCP syslog reception
SERVER_EOF
}
VERSION_SEQREV=14
. /usr/local/bin/sequencer.sh

View File

@@ -0,0 +1 @@
if $programname == 'CRON' and re_match($msg, "\\(root\\).*CMD.*") then stop

View File

@@ -0,0 +1 @@
if $programname == 'rngd' and re_match($msg, "stats:.*") then stop

Some files were not shown because too many files have changed in this diff Show More