line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package omnitool::installer; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
794
|
use 5.022001; |
|
1
|
|
|
|
|
4
|
|
4
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
19
|
|
5
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
39
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = "1.0.13"; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# for reading in configs |
10
|
1
|
|
|
1
|
|
1661
|
use File::Slurp; |
|
1
|
|
|
|
|
24572
|
|
|
1
|
|
|
|
|
70
|
|
11
|
1
|
|
|
1
|
|
1698
|
use IO::Prompter; |
|
1
|
|
|
|
|
37223
|
|
|
1
|
|
|
|
|
8
|
|
12
|
1
|
|
|
1
|
|
824
|
use Getopt::Long; |
|
1
|
|
|
|
|
10418
|
|
|
1
|
|
|
|
|
5
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# for creating config files |
15
|
1
|
|
|
1
|
|
731
|
use Template; |
|
1
|
|
|
|
|
19309
|
|
|
1
|
|
|
|
|
34
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# for building databases |
18
|
1
|
|
|
1
|
|
2065
|
use DBI; |
|
1
|
|
|
|
|
19184
|
|
|
1
|
|
|
|
|
67
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# for getting default hostname/domain name |
21
|
1
|
|
|
1
|
|
550
|
use Net::Domain qw( hostfqdn domainname ); |
|
1
|
|
|
|
|
8841
|
|
|
1
|
|
|
|
|
2673
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# create myself and try to grab arguments |
24
|
|
|
|
|
|
|
sub new { |
25
|
0
|
|
|
0
|
0
|
|
my $class = shift; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# our variables |
28
|
0
|
|
|
|
|
|
my ($self, $default_text, $hostname, $domainname, $options_map, $option_keys, $options, $options_file, $line, $name, $value, $option_key, $my_git_repo); |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# my default hostname and domain name |
31
|
0
|
|
|
|
|
|
$hostname = hostfqdn(); |
32
|
0
|
|
|
|
|
|
$domainname = domainname(); |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# where OmniTool lives |
35
|
0
|
|
|
|
|
|
$my_git_repo = 'https://github.com/ericschernoff/omnitool'; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# we need a map of what our options mean and their defaults |
38
|
|
|
|
|
|
|
# the default will be the second item in the array, if there is a default |
39
|
|
|
|
|
|
|
$options_map = { |
40
|
|
|
|
|
|
|
'config-file' => ['Full path to a file name which will include some/all of the config parameters for this installer, one name=value pairs, one per line. Provided args will override.'], |
41
|
|
|
|
|
|
|
'save-config-file' => ['If you wish to save a file with config parameters, provide a full path to the new file.'], |
42
|
|
|
|
|
|
|
'save-config-file-only' => ['Will save file with config parameters and exit without attempting to install; provide a full path to the new file.'], |
43
|
|
|
|
|
|
|
'othome' => ['The root directory for OmniTool, e.g. /usr/local/omnitool','/opt/omnitool'], |
44
|
|
|
|
|
|
|
'database-server' => ['Hostname or IP address of primary MySQL database server','127.0.0.1'], |
45
|
|
|
|
|
|
|
'db-username' => ['Username for connecting to MySQL; value must be provided'], |
46
|
|
|
|
|
|
|
'db-password' => ['Password for connecting to MySQL; value must be provided'], |
47
|
|
|
|
|
|
|
'init-vector' => ['Init vector for MySQL encryption; value longer than 10 characters must be provided'], |
48
|
|
|
|
|
|
|
'salt-phrase' => ['Salt phrase for MySQL encryption; value longer than 10 characters must be provided'], |
49
|
|
|
|
|
|
|
'ot-cookie-domain' => ['The domain name for the authentication cookie',$domainname], |
50
|
|
|
|
|
|
|
'ot-primary-hostname' => ['The full hostname for the main Web URI for this system',$hostname], |
51
|
|
|
|
|
|
|
'omnitool-admin' => ['The email address of the responsible party(ies) for this OmniTool system',$ENV{USER}.'@'.$domainname], |
52
|
0
|
|
|
|
|
|
'os-username' => ['The OS username who will run and own all OmniTool processes and resources',$ENV{USER}], |
53
|
|
|
|
|
|
|
'admin-ui-password' => [qq{The password for the 'omnitool_admin' user in the OT Admin Web UI; value must be provided}], |
54
|
|
|
|
|
|
|
'source_git_repo' => [qq{The source repo for OmniTool; change from default only if you have your own trusted fork.}, $my_git_repo], |
55
|
|
|
|
|
|
|
}; |
56
|
0
|
|
|
|
|
|
$option_keys = [ |
57
|
|
|
|
|
|
|
'config-file','save-config-file','save-config-file-only', |
58
|
|
|
|
|
|
|
'othome','database-server','db-username','db-password', |
59
|
|
|
|
|
|
|
'init-vector','salt-phrase', |
60
|
|
|
|
|
|
|
'omnitool-admin','os-username','admin-ui-password', |
61
|
|
|
|
|
|
|
'ot-cookie-domain','ot-primary-hostname','source_git_repo' |
62
|
|
|
|
|
|
|
]; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# what arguments did they send? |
65
|
0
|
|
|
|
|
|
$options = {}; |
66
|
0
|
|
|
|
|
|
GetOptions ($options, qw(-help+ |
67
|
|
|
|
|
|
|
-config-file=s -save-config-file=s -save-config-file-only=s |
68
|
|
|
|
|
|
|
-othome=s -database-server=s |
69
|
|
|
|
|
|
|
-db-username=s -db-password=s init-vector=s -salt-phrase=s -ot-cookie-domain=s |
70
|
|
|
|
|
|
|
-admin-ui-password=s -ot-primary-hostname=s -omnitool-admin=s -os-username=s |
71
|
|
|
|
|
|
|
-source_git_repo=s) |
72
|
|
|
|
|
|
|
); |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# do they just want to see the help screen? |
75
|
0
|
0
|
|
|
|
|
if ($$options{help}) { |
76
|
0
|
|
|
|
|
|
$self = bless { |
77
|
|
|
|
|
|
|
'options' => $options, |
78
|
|
|
|
|
|
|
'options_map' => $options_map, |
79
|
|
|
|
|
|
|
'option_keys' => $option_keys, |
80
|
|
|
|
|
|
|
}, $class; |
81
|
0
|
|
|
|
|
|
$self->print_help_text(); |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# if they sent a file that exists, read it to get any options now already sent |
85
|
0
|
0
|
0
|
|
|
|
if ($$options{'config-file'} && (-e $$options{'config-file'})) { |
86
|
0
|
|
|
|
|
|
$options_file = read_file($$options{'config-file'}); |
87
|
0
|
|
|
|
|
|
foreach $line (split /\n/, $options_file) { |
88
|
0
|
|
|
|
|
|
($name,$value) = split /\s?\=\s?/, $line; |
89
|
0
|
0
|
|
|
|
|
next if $$options{$name}; # skip if already filled |
90
|
0
|
|
|
|
|
|
$$options{$name} = $value |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# now we need to validate what we have so far, and prompt for what we do not have |
95
|
0
|
|
|
|
|
|
foreach $option_key (@$option_keys) { |
96
|
0
|
0
|
|
|
|
|
next if $option_key =~ /config-file/; # not for the config files |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
# if we do not have a value for this option, prompt for it |
99
|
0
|
0
|
|
|
|
|
if (!$$options{$option_key}) { |
100
|
|
|
|
|
|
|
# does it have a default? |
101
|
0
|
0
|
|
|
|
|
if ($$options_map{$option_key}[1]) { |
102
|
0
|
|
|
|
|
|
$default_text = ' [Default: '.$$options_map{$option_key}[1].']: '; |
103
|
|
|
|
|
|
|
} else { # no default |
104
|
0
|
|
|
|
|
|
$default_text = ' [No Default] : '; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# password mode? |
108
|
0
|
0
|
|
|
|
|
if ($option_key =~ /password/i) { |
109
|
0
|
|
|
|
|
|
$$options{$option_key} = prompt $$options_map{$option_key}[0].$default_text, -v, -echo=>'*'; |
110
|
|
|
|
|
|
|
} else { # OK to show |
111
|
0
|
|
|
|
|
|
$$options{$option_key} = prompt $$options_map{$option_key}[0].$default_text, -v; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# if it was not provided, take any calculated default |
115
|
0
|
0
|
|
|
|
|
$$options{$option_key} = $$options_map{$option_key}[1] if !length($$options{$option_key}); |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# if it is required and either does not exist or is not long enough, then die() here. |
118
|
0
|
0
|
0
|
|
|
|
if (!length($$options{$option_key}) && ($$options_map{$option_key}[0] =~ /must be provided/ || $option_key eq 'source_git_repo')) { |
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
119
|
0
|
|
|
|
|
|
die(qq{ERROR: You must provide a value for the '$option_key' option. Please run 'omnitool-installer --help' for details.}."\n"); |
120
|
|
|
|
|
|
|
} elsif (length($$options{$option_key}) < 10 && $$options_map{$option_key}[0] =~ /longer than 10 characters/) { |
121
|
0
|
|
|
|
|
|
die(qq{ERROR: Value for '$option_key' option must be 10 characters or greater. Please run 'omnitool-installer --help' for details.}."\n"); |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# set up the object with all the options data |
128
|
0
|
|
|
|
|
|
$self = bless { |
129
|
|
|
|
|
|
|
'options' => $options, |
130
|
|
|
|
|
|
|
'options_map' => $options_map, |
131
|
|
|
|
|
|
|
'option_keys' => $option_keys, |
132
|
|
|
|
|
|
|
}, $class; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# do they want to save these configs back out (and potentially exit)? |
135
|
0
|
0
|
0
|
|
|
|
if ($self->{options}{'save-config-file'} || $self->{options}{'save-config-file-only'}) { |
136
|
0
|
|
|
|
|
|
$self->save_config_file(); |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# if we are still alive, send it back |
140
|
0
|
|
|
|
|
|
return $self; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# method to undertake all the installation tasks |
144
|
|
|
|
|
|
|
sub do_the_installation { |
145
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
146
|
|
|
|
|
|
|
|
147
|
0
|
|
|
|
|
|
my (@sub_directories, $config_file, $sub_directory, $the_sub_directory, $belt, $db_info, $distribution_directory, $htdocs_source, $htdocs_link, $omnitool_pm_source, $omnitool_pm_link, @ot_code_pieces, $ot_code_piece, $ot_code_source, $ot_code_link, @web_urls, $next_steps,$next_steps_file); |
148
|
|
|
|
|
|
|
|
149
|
0
|
|
|
|
|
|
print "\n\nATTEMPTING INSTALLATION TASKS:\n\n"; |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
# here are the sub-directories we need |
152
|
0
|
|
|
|
|
|
@sub_directories = qw( |
153
|
|
|
|
|
|
|
code code/omnitool code/omnitool/applications |
154
|
|
|
|
|
|
|
configs configs/ssl_cert |
155
|
|
|
|
|
|
|
files hash_cache |
156
|
|
|
|
|
|
|
htdocs log log/archive |
157
|
|
|
|
|
|
|
tmp tmp/docs tmp/email_incoming tmp/pids |
158
|
|
|
|
|
|
|
); |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# start with the home directory |
161
|
0
|
0
|
|
|
|
|
if (!(-d $self->{options}{othome})) { |
162
|
0
|
|
|
|
|
|
mkdir($self->{options}{othome}, 0755); |
163
|
0
|
|
|
|
|
|
print "Created OmniTool root directory at ".$self->{options}{othome}."\n"; |
164
|
|
|
|
|
|
|
} else { |
165
|
0
|
|
|
|
|
|
print "OmniTool root directory already exists at ".$self->{options}{othome}."\n"; |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# no go through the sub directories |
169
|
0
|
|
|
|
|
|
foreach $sub_directory (@sub_directories) { |
170
|
0
|
|
|
|
|
|
$the_sub_directory = $self->{options}{othome}.'/'.$sub_directory; |
171
|
0
|
0
|
|
|
|
|
if (!(-d $the_sub_directory)) { |
172
|
0
|
|
|
|
|
|
mkdir($the_sub_directory, 0755); |
173
|
0
|
|
|
|
|
|
print "Created $the_sub_directory\n"; |
174
|
|
|
|
|
|
|
} else { |
175
|
0
|
|
|
|
|
|
print "Skipped $the_sub_directory - already exists\n"; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
# our distribution directory will be here: |
180
|
0
|
|
|
|
|
|
$distribution_directory = $self->{options}{othome}.'/distribution'; |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# now pull down the code |
183
|
0
|
0
|
|
|
|
|
if (-d $distribution_directory.'/omnitool') { # already there, need to do a 'git pull' |
184
|
0
|
|
|
|
|
|
chdir $distribution_directory; |
185
|
0
|
|
|
|
|
|
system('git','pull'); |
186
|
0
|
|
|
|
|
|
print "Latest OmniTool code repo *pulled* into $distribution_directory\n"; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
} else { # need to do a clone |
189
|
0
|
|
|
|
|
|
system('git','clone',$self->{options}{source_git_repo},$distribution_directory); |
190
|
0
|
|
|
|
|
|
print "Latest OmniTool code repo *cloned* into $distribution_directory\n"; |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# link distribution/htdocs to OTHOME/htdocs/omnitool |
194
|
0
|
|
|
|
|
|
$htdocs_source = $distribution_directory.'/htdocs'; |
195
|
0
|
|
|
|
|
|
$htdocs_link = $self->{options}{othome}.'/htdocs/omnitool'; |
196
|
0
|
0
|
|
|
|
|
if (!(-l $htdocs_link)) { |
197
|
0
|
|
|
|
|
|
symlink $htdocs_source, $htdocs_link; |
198
|
0
|
|
|
|
|
|
print "Linked static (HTML/JS/CSS/Images) collateral to $htdocs_link.\n"; |
199
|
|
|
|
|
|
|
} else { |
200
|
0
|
|
|
|
|
|
print "Skipped link to static (HTML/JS/CSS/Images) collateral to $htdocs_link; symlink already exists.\n"; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# now link to the code, but make it possible for them to write their own applications under $OTPERL/applications |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# first: omnitool.pm |
206
|
0
|
|
|
|
|
|
$omnitool_pm_source = $distribution_directory.'/omnitool.pm'; |
207
|
0
|
|
|
|
|
|
$omnitool_pm_link = $self->{options}{othome}.'/code/omnitool.pm'; |
208
|
0
|
0
|
|
|
|
|
if (!(-l $omnitool_pm_link)) { |
209
|
0
|
|
|
|
|
|
symlink $omnitool_pm_source, $omnitool_pm_link; |
210
|
0
|
|
|
|
|
|
print "Linked omnitool.pm to $omnitool_pm_link.\n"; |
211
|
|
|
|
|
|
|
} else { |
212
|
0
|
|
|
|
|
|
print "Skipped link of omnitool.pm to $omnitool_pm_link; symlink already exists.\n"; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
# now the bits under the actual directory |
216
|
0
|
|
|
|
|
|
@ot_code_pieces = qw( |
217
|
|
|
|
|
|
|
common dispatcher.pm main.psgi omniclass omniclass.pm scripts |
218
|
|
|
|
|
|
|
static_files tool tool.pm |
219
|
|
|
|
|
|
|
applications/otadmin applications/sample_apps |
220
|
|
|
|
|
|
|
); |
221
|
0
|
|
|
|
|
|
foreach $ot_code_piece (@ot_code_pieces) { |
222
|
0
|
|
|
|
|
|
$ot_code_source = $distribution_directory.'/omnitool/'.$ot_code_piece; |
223
|
0
|
|
|
|
|
|
$ot_code_link = $self->{options}{othome}.'/code/omnitool/'.$ot_code_piece; |
224
|
0
|
0
|
|
|
|
|
if (!(-l $ot_code_link)) { |
225
|
0
|
|
|
|
|
|
symlink $ot_code_source, $ot_code_link; |
226
|
0
|
|
|
|
|
|
print "Linked $ot_code_source to $ot_code_link.\n"; |
227
|
|
|
|
|
|
|
} else { |
228
|
0
|
|
|
|
|
|
print "Skipped link of $ot_code_source to $ot_code_link; symlink already exists.\n"; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# now, let's set up configs/dbinfo.txt |
233
|
0
|
|
|
|
|
|
$db_info = $self->{options}{'db-username'}."\n".$self->{options}{'db-password'}; |
234
|
0
|
|
|
|
|
|
$self->stash_some_text($db_info, $self->{options}{othome}.'/configs/dbinfo.txt'); |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
# now create the configuration files |
237
|
0
|
|
|
|
|
|
foreach $config_file ('bash_aliases.tt','mysql_omnitool.cnf.tt','omnitool.service.tt','omnitool_apache.conf.tt','start_omnitool.bash.tt') { |
238
|
0
|
|
|
|
|
|
$self->create_config_files($config_file); |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
# symlink over code map |
242
|
0
|
|
|
|
|
|
symlink $self->{options}{othome}.'/distribution/configs/ot6_modules.yml', $self->{options}{othome}.'/configs/ot6_modules.yml'; |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
# if the user who will run OT6 is not the same username running this script, run a chown |
245
|
0
|
0
|
|
|
|
|
if ($ENV{USER} ne $self->{options}{'os-username'}) { |
246
|
0
|
|
|
|
|
|
system('chown -R '.$self->{options}{'os-username'}.' '.$self->{options}{othome}); |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
# final step is the database work |
250
|
|
|
|
|
|
|
# we need to log into the database and see if we need to create the 'omnitool' and 'otstatedata' DB's |
251
|
|
|
|
|
|
|
# and then set up their OT6 Admin user |
252
|
0
|
|
|
|
|
|
$self->setup_databases(); |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# what is left for them to do? |
255
|
0
|
|
|
|
|
|
$web_urls[0] = 'https://'.$self->{options}{'ot-primary-hostname'}.'/sample_apps_admin'; |
256
|
0
|
|
|
|
|
|
$web_urls[1] = 'https://'.$self->{options}{'ot-primary-hostname'}.'/sample_tools'; |
257
|
0
|
|
|
|
|
|
$web_urls[2] = 'https://'.$self->{options}{'ot-primary-hostname'}.'/apps_admin'; |
258
|
0
|
|
|
|
|
|
$web_urls[3] = 'https://'.$self->{options}{'ot-primary-hostname'}.'/apps_admin#/tools/view_module_docs'; |
259
|
0
|
|
|
|
|
|
$next_steps = qq{ |
260
|
|
|
|
|
|
|
OMNITOOL INSTALLATION IS COMPLETE. |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
Next Steps: |
263
|
|
|
|
|
|
|
1. Adjust your CLI environment by adding this to ~/.bash_aliases: |
264
|
|
|
|
|
|
|
source $self->{options}{othome}/configs/bash_aliases |
265
|
|
|
|
|
|
|
2. Bring in the Apache config (or adjust Nginix to taste). For Ubuntu: |
266
|
|
|
|
|
|
|
cd /etc/apache2/conf-enabled ; ln -s $self->{options}{othome}/configs/omnitool_apache.conf |
267
|
|
|
|
|
|
|
3. Install SSL certificates in here: $self->{options}{othome}/configs/ssl_cert |
268
|
|
|
|
|
|
|
- Self-signing cert info: https://httpd.apache.org/docs/2.4/ssl/ssl_faq.html#selfcert |
269
|
|
|
|
|
|
|
- You will need to edit lines 76-78 in $self->{options}{othome}/configs/omnitool_apache.conf |
270
|
|
|
|
|
|
|
4. Restart Apache: sudo systemctl restart apache2 |
271
|
|
|
|
|
|
|
5. Review/tweak and install the special MySQL Config File. For Ubuntu: |
272
|
|
|
|
|
|
|
cd /etc/mysql/mysql.conf.d ; sudo cp /opt/omnitool/configs/mysql_omnitool.cnf ./ |
273
|
|
|
|
|
|
|
\$EDITOR mysql_omnitool.cnf |
274
|
|
|
|
|
|
|
sudo systemctl restart mysql |
275
|
|
|
|
|
|
|
6. Reviw/tweak the script to start the Plack Service, especially lines 24-42: |
276
|
|
|
|
|
|
|
\$EDITOR /opt/omnitool/configs/start_omnitool.bash |
277
|
|
|
|
|
|
|
# Note the 'RECAPTCHA' vars if you want to use Google's ReCaptcha service. |
278
|
|
|
|
|
|
|
7. Start the Plack Service: |
279
|
|
|
|
|
|
|
sudo /opt/omnitool/configs/start_omnitool.bash start |
280
|
|
|
|
|
|
|
(Look at the omnitool.service SystemD script under /opt/omnitool/configs/ as well.) |
281
|
|
|
|
|
|
|
8. Check out the sample apps: |
282
|
|
|
|
|
|
|
Admin: $web_urls[0] |
283
|
|
|
|
|
|
|
User-Facing: $web_urls[1] |
284
|
|
|
|
|
|
|
9. Read some Perl docs: $web_urls[3] |
285
|
|
|
|
|
|
|
10. Get Started on Your Apps: $web_urls[2] |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
** The username for the Web URL's in steps 8-10 will be 'omnitool_admin' with the |
288
|
|
|
|
|
|
|
password you gave for the ''admin-ui-password' option. ** |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
If you have any questions, please reach out to ericschernoff\@gmail.com . |
291
|
|
|
|
|
|
|
}; |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
# save that to their home directory |
294
|
0
|
|
|
|
|
|
$next_steps_file = $self->{options}{othome}.'/configs/omnitool_next_steps.txt'; |
295
|
0
|
|
|
|
|
|
write_file($next_steps_file,$next_steps); |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# output it, telling them where it is |
298
|
0
|
|
|
|
|
|
print $next_steps."\n(A copy of these next steps have been saved to $next_steps_file .\n"; |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# stripped-down version of text-stashing |
303
|
|
|
|
|
|
|
sub stash_some_text { |
304
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
305
|
|
|
|
|
|
|
|
306
|
0
|
|
|
|
|
|
my ($text_to_stash,$file_location) = @_; |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# garble it up |
309
|
0
|
|
|
|
|
|
my $obfuscated = unpack "h*", $text_to_stash; |
310
|
|
|
|
|
|
|
# get this out like: |
311
|
|
|
|
|
|
|
# $obfuscated = read_file($file_location); |
312
|
|
|
|
|
|
|
# my $stashed_text = pack "h*", $obfuscated; |
313
|
|
|
|
|
|
|
# print $stashed_text."\n"; |
314
|
|
|
|
|
|
|
# This is 0.0000001% of what pack() can do, please see: http://perldoc.perl.org/functions/pack.html |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# stash it out |
317
|
0
|
|
|
|
|
|
write_file( $file_location, $obfuscated); |
318
|
|
|
|
|
|
|
|
319
|
0
|
|
|
|
|
|
return 1; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# method to create new config files from my templates |
323
|
|
|
|
|
|
|
sub create_config_files { |
324
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
# the name of the config file template we are going to create |
327
|
0
|
|
|
|
|
|
my ($config_filename) = @_; |
328
|
|
|
|
|
|
|
# return if blank or non-existent |
329
|
0
|
0
|
0
|
|
|
|
return if !$config_filename || !(-e $self->{options}{othome}.'/distribution/configs/'.$config_filename); |
330
|
|
|
|
|
|
|
|
331
|
0
|
|
|
|
|
|
my ($destination_file, $output, $tt, $key, $new_key); |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
# where is it going? |
334
|
0
|
|
|
|
|
|
$destination_file = $self->{options}{othome}.'/configs/'.$config_filename; |
335
|
0
|
|
|
|
|
|
$destination_file =~ s/.tt$//; |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
# if it exists, abort |
338
|
0
|
0
|
|
|
|
|
if (-e $destination_file) { |
339
|
0
|
|
|
|
|
|
print "SKIPPED: Can not overwrite config file: $destination_file ; please delete and re-attempt or adjust by hand.\n"; |
340
|
0
|
|
|
|
|
|
return; |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
# i hate dashes, but felt like they were standard in the args |
344
|
0
|
|
|
|
|
|
foreach $key ('database-server','omnitool-admin','os-username','init-vector','salt-phrase','ot-cookie-domain','ot-primary-hostname') { |
345
|
0
|
|
|
|
|
|
($new_key = $key) =~ s/-/_/g; |
346
|
0
|
|
|
|
|
|
$self->{options}{$new_key} = $self->{options}{$key}; |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
# prepare template toolkit |
350
|
0
|
|
|
|
|
|
$output = ''; # where the text shall go |
351
|
|
|
|
|
|
|
$tt = Template->new({ |
352
|
|
|
|
|
|
|
ENCODING => 'utf8', |
353
|
0
|
|
|
|
|
|
INCLUDE_PATH => $self->{options}{othome}.'/distribution/configs/', |
354
|
|
|
|
|
|
|
OUTPUT => \$output, |
355
|
|
|
|
|
|
|
}); |
356
|
|
|
|
|
|
|
# process the template |
357
|
0
|
|
|
|
|
|
$tt->process($config_filename, $self, $output, {binmode => ':encoding(utf8)'}); |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# save the new file under OTHOME/configs |
360
|
0
|
|
|
|
|
|
write_file($destination_file, $output); |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
# if it's start_omnitool.bash.tt, make it executable |
363
|
0
|
0
|
|
|
|
|
if ($config_filename eq 'start_omnitool.bash.tt') { |
364
|
0
|
|
|
|
|
|
chmod 0744, $destination_file; |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
# symlink over code map |
368
|
0
|
|
|
|
|
|
symlink $self->{options}{othome}.'/distribution/configs/ot6_modules.yml', $self->{options}{othome}.'/configs/ot6_modules.yml'; |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
# report success |
371
|
0
|
|
|
|
|
|
print "Created config file $destination_file ; please verify and adjust.\n"; |
372
|
0
|
|
|
|
|
|
return; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
# method to set up the 'omnitool' and 'otstatedata' databases |
376
|
|
|
|
|
|
|
sub setup_databases { |
377
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
378
|
|
|
|
|
|
|
|
379
|
0
|
|
|
|
|
|
my ($dsn, $dbh, $db_name, $sth, $exists, $safe_to_modify); |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# try to make the connection |
382
|
0
|
|
|
|
|
|
$dsn = qq{DBI:mysql:database=information_schema;host=}.$self->{options}{'database-server'}.qq{;port=3306}; |
383
|
0
|
|
|
|
|
|
$dbh = DBI->connect($dsn, $self->{options}{'db-username'}, $self->{options}{'db-password'},{ PrintError => 1, RaiseError=>1, mysql_enable_utf8=>8 }); |
384
|
0
|
|
|
|
|
|
$dbh->{LongReadLen} = 1000000; |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
# check to see if it has our databases |
387
|
0
|
|
|
|
|
|
foreach $db_name ('omnitool','otstatedata','omnitool_applications','omnitool_samples','sample_tools') { |
388
|
0
|
|
|
|
|
|
$sth = $dbh->prepare(qq{select CATALOG_NAME from SCHEMATA where SCHEMA_NAME='$db_name'}); |
389
|
0
|
0
|
|
|
|
|
$sth->execute or print $dbh->errstr."\n"; |
390
|
0
|
|
|
|
|
|
($exists) = $sth->fetchrow_array; |
391
|
0
|
0
|
|
|
|
|
if ($exists) { # if it exists, skip it |
392
|
0
|
|
|
|
|
|
print "SKIPPED: $db_name already exists and was not be overwritten.\n"; |
393
|
|
|
|
|
|
|
} else { # otherwise, load it in |
394
|
0
|
|
|
|
|
|
$sth = $dbh->prepare(qq{create database $db_name}); |
395
|
0
|
0
|
|
|
|
|
$sth->execute or print $dbh->errstr."\n"; |
396
|
0
|
|
|
|
|
|
system('mysql -u'.$self->{options}{'db-username'}.' -p'.$self->{options}{'db-password'}.' -h'.$self->{options}{'database-server'}.' '.$db_name.' < '.$self->{options}{othome}.'/distribution/schema/'.$db_name.'.sql'); |
397
|
0
|
|
|
|
|
|
print "Created $db_name from included schema.\n"; |
398
|
|
|
|
|
|
|
# so we know we can update the databases below with out install tweaks |
399
|
0
|
|
|
|
|
|
$$safe_to_modify{$db_name} = 1; |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
# start tweaking the omnitool(_*) DB's |
404
|
|
|
|
|
|
|
|
405
|
0
|
0
|
|
|
|
|
if ($$safe_to_modify{omnitool}) { # can modify core omnitool admin |
406
|
|
|
|
|
|
|
# fix the password for the 'omnitool_admin' user in all three databases |
407
|
0
|
|
|
|
|
|
foreach $db_name ('omnitool','omnitool_applications','omnitool_samples') { |
408
|
0
|
|
|
|
|
|
$sth = $dbh->prepare('update '.$db_name.qq{.omnitool_users set password=sha2(?,224) where username='omnitool_admin'}); |
409
|
0
|
0
|
|
|
|
|
$sth->execute($self->{options}{'admin-ui-password'}) or print $dbh->errstr."\n"; |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
|
412
|
0
|
|
|
|
|
|
print "Set Password for 'omnitool_admin' user in the OmniTool Admin Web UI.\n"; |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
# fix the name and hostname of the Apps for their domain |
415
|
0
|
|
|
|
|
|
$sth = $dbh->prepare(qq{update omnitool.instances set name=?, hostname=? where code='10'}); |
416
|
0
|
0
|
|
|
|
|
$sth->execute('Admin for '.ucfirst($self->{options}{'ot-cookie-domain'}), 'apps-admin.'.$self->{options}{'ot-cookie-domain'}) or print $dbh->errstr."\n"; |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
# fix the name and hostname of the Sample Apps |
419
|
0
|
|
|
|
|
|
$sth = $dbh->prepare(qq{update omnitool.instances set hostname=? where code='9'}); |
420
|
0
|
0
|
|
|
|
|
$sth->execute('sample-apps-admin.'.$self->{options}{'ot-cookie-domain'}) or print $dbh->errstr."\n"; |
421
|
|
|
|
|
|
|
|
422
|
0
|
|
|
|
|
|
print "Updated Name, Hostname for Custom Applications Admin UI.\n"; |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
} else { |
425
|
|
|
|
|
|
|
|
426
|
0
|
|
|
|
|
|
print "SKIPPED: Could not modify 'omnitool_admin' password; Core 'omnitool' database already exists.\n"; |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
# Update all database server records |
431
|
0
|
|
|
|
|
|
foreach $db_name ('omnitool','omnitool_applications','omnitool_samples') { |
432
|
0
|
0
|
|
|
|
|
if ($$safe_to_modify{$db_name}) { |
433
|
0
|
|
|
|
|
|
$sth = $dbh->prepare('update '.$db_name.qq{.database_servers set hostname=?}); |
434
|
0
|
0
|
|
|
|
|
$sth->execute($self->{options}{'database-server'}) or print $dbh->errstr."\n"; |
435
|
|
|
|
|
|
|
|
436
|
0
|
|
|
|
|
|
print "Set database server hostname for $db_name.\n"; |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
} else { |
439
|
0
|
|
|
|
|
|
print "SKIPPED: Could not set database server hostname for $db_name; that database already exists.\n"; |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
} |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
# method to save out the config file if they sent the right arguments |
446
|
|
|
|
|
|
|
sub save_config_file { |
447
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
448
|
|
|
|
|
|
|
|
449
|
0
|
|
|
|
|
|
my ($option_key, $options_config); |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
# just need a set of name=value pairs, one per line |
452
|
0
|
|
|
|
|
|
foreach $option_key (@{ $self->{option_keys} }) { |
|
0
|
|
|
|
|
|
|
453
|
0
|
0
|
|
|
|
|
next if $option_key =~ /config-file/; # not for the config files |
454
|
0
|
|
|
|
|
|
$options_config .= $option_key.'='.$self->{options}{$option_key}."\n"; |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
# take off the last character |
458
|
0
|
|
|
|
|
|
chomp($options_config); |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
# just save? |
461
|
0
|
0
|
|
|
|
|
if ($self->{options}{'save-config-file'}) { |
|
|
0
|
|
|
|
|
|
462
|
|
|
|
|
|
|
|
463
|
0
|
|
|
|
|
|
write_file($self->{options}{'save-config-file'}, $options_config); |
464
|
|
|
|
|
|
|
|
465
|
0
|
|
|
|
|
|
print "\n\nConfig options file saved to ".$self->{options}{'save-config-file'}."\n\n"; |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
# or save an exit |
468
|
|
|
|
|
|
|
} elsif ($self->{options}{'save-config-file-only'}) { |
469
|
|
|
|
|
|
|
|
470
|
0
|
|
|
|
|
|
write_file($self->{options}{'save-config-file-only'}, $options_config); |
471
|
|
|
|
|
|
|
|
472
|
0
|
|
|
|
|
|
print "\n\nConfig options file saved to ".$self->{options}{'save-config-file-only'}." and no further action taken.\n\n"; |
473
|
0
|
|
|
|
|
|
exit; |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
# method to print a help screen, based on map above |
478
|
|
|
|
|
|
|
sub print_help_text { |
479
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
# start with intro |
482
|
0
|
|
|
|
|
|
print qq{ |
483
|
|
|
|
|
|
|
OmniTool Installer: Retrieves and installs the OmniTool Web Framework onto this system. |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
Usage: omnitool_installer [OPTIONS] |
486
|
|
|
|
|
|
|
Must provide either a config_file or all options, where options are: |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
Git Repo for OmniTool: https://github.com/ericschernoff/omnitool |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
OmniTool Website: http://www.omnitool.org |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
Requires Ubuntu 16.04+ (or distro based on 16.04), as well as Perl 5.22+ and Git. |
493
|
|
|
|
|
|
|
Also requires MySQL 5.7+ or MariaDB 10.3+ here or close by, and it's no fun without |
494
|
|
|
|
|
|
|
Apache installed. |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
Before running, please install the following packages: |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
zlib1g-dev libssl-dev install build-essential cpanminus perl-doc |
499
|
|
|
|
|
|
|
mysql-server libmysqlclient-dev apache2 |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
Then, you will need to enable a few Apache modules: |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
a2enmod proxy ssl headers proxy_http rewrite |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
}; |
506
|
0
|
|
|
|
|
|
foreach my $option_key (@{ $self->{option_keys} }) { |
|
0
|
|
|
|
|
|
|
507
|
0
|
|
|
|
|
|
print '--'.$option_key.' '; |
508
|
0
|
0
|
|
|
|
|
if ($self->{options_map}{$option_key}[1]) { |
509
|
0
|
|
|
|
|
|
print $self->{options_map}{$option_key}[0].': [Default: '.$self->{options_map}{$option_key}[1].']'; |
510
|
|
|
|
|
|
|
} else { |
511
|
0
|
|
|
|
|
|
print $self->{options_map}{$option_key}[0].': [No Default]'; |
512
|
|
|
|
|
|
|
} |
513
|
0
|
|
|
|
|
|
print "\n\n"; |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
# done here |
517
|
0
|
|
|
|
|
|
exit; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
1; |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
__END__ |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
=encoding utf-8 |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
=head1 NAME |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
omnitool::installer - Install the OmniTool Web Application Framework |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
Provides the 'omnitool_installer' script to install OmniTool on your system. |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
=head1 END-OF-LIFE / DEPRECATION |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
This system is no longer under active development. OmniTool should not be used for any new projects. |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
This repo contains some interesting ideas and perhaps a few solutions, so this repo will remain online for archive purposes. If you are interested in taking over this project, please let me know. |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
=head1 SYNOPSIS |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
# To provide installation details interactively then install: |
541
|
|
|
|
|
|
|
omnitool_installer |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
# Safer approach: provide the installation details interactively and save config file: |
544
|
|
|
|
|
|
|
omnitool_installer --save-config-file-only=/some/path/ot_install.config |
545
|
|
|
|
|
|
|
# then run |
546
|
|
|
|
|
|
|
omnitool_installer --config-file=/some/path/ot_install.config |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
# Be sure to delete/protect ot_install.config |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
# To see help and exit: |
551
|
|
|
|
|
|
|
omnitool_installer --help |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
=head1 DESCRIPTION |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
OmniTool allows you to build web application suites very quickly and with minimal code. It is |
556
|
|
|
|
|
|
|
designed to simplify and speed up the development process, reducing code requirements to only |
557
|
|
|
|
|
|
|
the specific features and logic for the target application. The resulting applications are |
558
|
|
|
|
|
|
|
mobile-responsive and API-enabled with no extra work by the developers. |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
For lots more information on how this works, including demos, examples, and lots of documentation, |
561
|
|
|
|
|
|
|
please visit L<http://www.omnitool.org/> |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
The GitHub Repo for OmniTool is L<https://github.com/ericschernoff/omnitool> |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
=head2 PREREQUISITES |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
OmniTool has been developed and tested with the following base components: |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
=over |
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
=item - Ubuntu 16.04 Server |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
=item - Perl 5.22 |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
=item - Git 2.10 |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
=item - MySQL 5.7 or MariaDB 10.3 (at least the client libraries if separate DB server) |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
=item - Apache 2.4 |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
=back |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
You can very likely make it work on FreeBSD 10.1+ or a recent release of RHEL, Fedora, or CentOS. I am not able |
584
|
|
|
|
|
|
|
to provide detailed instructions on each of these -- volunteers would be very welcome! |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
Prior to installation, the following packages will need to be installed via 'sudo apt install': |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
=over |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
=item - build-essential |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
=item - zlib1g-dev |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
=item - libssl-dev |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=item - cpanminus |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
=item - perl-doc |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
=item - mysql-server |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
=item - libmysqlclient-dev |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
=item - apache2 |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
=back |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
Then, you will need to enable a few Apache modules: |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
=over |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
sudo a2enmod proxy ssl headers proxy_http rewrite |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
=back |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
Again, these are Ubuntu 16.04 commands. I am quite sure you can make this work with the other BSD, Linux |
617
|
|
|
|
|
|
|
flavors, as well as with Nginix instead of Apache if you prefer. |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
=head2 ACKNOWLEDGEMENTS |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
I am very appreciative to my employer, Cisco Systems, Inc., for allowing this software to be |
622
|
|
|
|
|
|
|
released to the community as open source. (IP Central ID: 153330984). |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
I am also grateful to Mohsen Hosseini for allowing me to include his most excellent Ace |
625
|
|
|
|
|
|
|
Admin as part of this software. |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
=head1 LICENSE |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
MIT License |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
Copyright (c) 2017 Eric Chernoff |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
634
|
|
|
|
|
|
|
of this software and associated documentation files (the "Software"), to deal |
635
|
|
|
|
|
|
|
in the Software without restriction, including without limitation the rights |
636
|
|
|
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
637
|
|
|
|
|
|
|
copies of the Software, and to permit persons to whom the Software is |
638
|
|
|
|
|
|
|
furnished to do so, subject to the following conditions: |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all |
641
|
|
|
|
|
|
|
copies or substantial portions of the Software. |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
644
|
|
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
645
|
|
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
646
|
|
|
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
647
|
|
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
648
|
|
|
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
649
|
|
|
|
|
|
|
SOFTWARE. |
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
=head1 AUTHOR |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
Eric Chernoff E<lt>ericschernoff@gmail.comE<gt> |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
=cut |
656
|
|
|
|
|
|
|
|