Merge branch 'dev' of feistymeow.org:feisty_meow into dev
[feisty_meow.git] / scripts / system / common_sysadmin.sh
1 #!/bin/bash
2
3 # this is a library of functions shared by scripts in the system folder.
4 #
5 # Author: Chris Koeritz
6
7 ############################################################################
8
9 # bind9 methods...
10
11 # removes a full domain from the DNS.
12 function remove_domain_file()
13 {
14   local domain_name="$1"; shift
15
16   local domain_file="/etc/bind/${domain_name}.conf"
17   if [ -f "$domain_file" ]; then
18     # don't destroy, just shuffle.
19     \mv -f "$domain_file" "/tmp/$(basename ${domain_file})-old-${RANDOM}"
20     test_or_die "removing domain file: $domain_file"
21   else
22     echo "Did not see a domain file to remove: $domain_file"
23   fi
24 }
25
26 # creates a totally new domain config file for DNS.
27 function write_new_domain_file()
28 {
29   local domain_name="$1"; shift
30
31   local domain_file="/etc/bind/${domain_name}.conf"
32
33   echo "adding a totally new domain called $domain_name"
34   echo "using the config file: $domain_file"
35
36   if [ -f $domain_file ]; then
37     echo
38     echo "The domain configuration file already exists at:"
39     echo "  $domain_file"
40     echo "Since we don't want to tear that down if it has specialized configuration"
41     echo "data in it, we will just leave it in place and consider our job done."
42     echo
43     exit 0
44   fi
45
46   echo "
47 \$TTL 1W
48 @       IN SOA  @       ${SERVER_ADMIN}. (
49                 2017100801 ; serial
50                 2H ; refresh
51                 8M ; retry
52                 14D ; expiry
53                 6H ) ; minimum
54
55         IN NS           ${MAIN_NAME_SERVER}.
56         IN MX   10      ${MAIL_SERVER}.
57
58 ${domain_name}. IN A    ${IP_ADDRESS}
59         IN HINFO        \"linux server\" \"${DISTRO}\"
60 " >"$domain_file"
61
62   # our personalized configuration approach wants the real owner to own the file.
63   chown "$(logname):$(logname)" $domain_file
64   test_or_die "setting ownership on: $domain_file"
65 }
66
67 # takes a zone back out of the local conf file for bind
68 function remove_zone_for_domain()
69 {
70   local domain_name="$1"; shift
71
72   local domain_file="/etc/bind/${domain_name}.conf"
73
74   # eat the zone file definition.  this will botch up badly if more text was added
75   # or the zone info shrank.
76   create_chomped_copy_of_file "/etc/bind/named.conf.local" "zone.*${domain_name}" 6
77 }
78
79 # hooks up a new config file into bind's list of zones.
80 function add_zone_for_new_domain()
81 {
82   local domain_name="$1"; shift
83
84   local domain_file="/etc/bind/${domain_name}.conf"
85
86   echo "adding a new domain configured by ${domain_file} into"
87   echo "the named.conf.local configuration file."
88
89   # append the reference to the new conf file in the zone list.
90   echo "
91 zone \"${domain_name}\" in {
92         file \"${domain_file}\";
93         type master;
94         allow-query { any; };
95 };
96
97 ////////////////////////////////////////////////////////////////////////////
98
99 " >> /etc/bind/named.conf.local
100
101   # keep ownership for the real user.
102   chown "$(logname):$(logname)" /etc/bind/named.conf.local
103   test_or_die "setting ownership on: /etc/bind/named.conf.local"
104 }
105
106 # zaps a subdomain out of the containing domain file.
107 function remove_subdomain()
108 {
109   local old_domain="$1"; shift
110
111   # split up the full domain name into subdomain portion and containing domain.
112   local subdomain="${old_domain%.*.*}"
113   local containing_domain="${old_domain#*.}"
114
115   echo "removing subdomain $subdomain from containing domain $containing_domain"
116
117   local domain_file="/etc/bind/${containing_domain}.conf"
118   # see if config file already exists; if not, complain.
119   if [ ! -f "$domain_file" ]; then
120     echo "The domain configuration file for $old_domain is missing."
121     echo "It should already be present in: $domain_file"
122     echo "We cannot remove a subdomain if the containing domain isn't there."
123     exit 1
124   fi
125
126   # see if subdomain already present in config.
127   if ! grep -q "$old_domain" "$domain_file"; then
128     echo "The subdomain $subdomain is already missing from the domain"
129     echo "configuration file: $domain_file"
130     echo "Our work is apparently done for removing it."
131     return 0
132   fi
133
134   create_chomped_copy_of_file "$domain_file" "${old_domain}" 2
135 }
136
137 # adds a new subdomain under a containing domain.
138 function add_new_subdomain()
139 {
140   local new_domain="$1"; shift
141
142   # split up the full domain name into subdomain portion and containing domain.
143   local subdomain="${new_domain%.*.*}"
144   local containing_domain="${new_domain#*.}"
145
146   echo "adding a subdomain $subdomain to containing domain $containing_domain"
147
148   local domain_file="/etc/bind/${containing_domain}.conf"
149   # see if config file already exists; if not, complain.
150   if [ ! -f "$domain_file" ]; then
151     echo "The domain configuration file for $new_domain is missing."
152     echo "It should already be present in: $domain_file"
153     echo "Please add the containing domain before trying to add a subdomain."
154     exit 1
155   fi
156
157   # see if subdomain already present in config.
158   if grep -q "$new_domain" "$domain_file"; then
159     echo "The subdomain $subdomain already seems to exist in the domain"
160     echo "configuration file: $domain_file"
161     echo "We are considering our work done; if you want to modify the subdomain,"
162     echo "then please call remove_domain on it first."
163     return 0
164   fi
165
166   # append the new subdomain into the config file.
167   echo "${subdomain}.${containing_domain}.    IN A    ${IP_ADDRESS}
168         IN HINFO \"linux server\" \"${DISTRO}\"
169 " >> /etc/bind/${containing_domain}.conf
170
171   # keep ownership for real user.
172   chown "$(logname):$(logname)" "/etc/bind/${containing_domain}.conf"
173   test_or_die "setting ownership on: /etc/bind/${containing_domain}.conf"
174 }
175
176 function restart_bind()
177 {
178   echo restarting DNS server.
179   service bind9 restart
180   if [ $? -ne 0 ]; then
181     echo "The bind service did not restart properly.  Please check the error logs."
182     exit 1
183   fi
184   echo DNS service restarted.
185 }
186
187 ############################################################################
188
189 # samba server helper functions...
190
191 function restart_samba
192 {
193   echo restarting samba server.
194   service smbd restart
195   if [ $? -ne 0 ]; then
196     echo "The samba service did not restart properly.  Please check the error logs."
197     exit 1
198   fi
199   service nmbd restart
200   if [ $? -ne 0 ]; then
201     echo "The samba name service (nmbd) did not restart properly.  This may not always be fatal, so we are ignoring it, but you may want to check the error logs."
202   fi
203   echo samba service restarted.
204 }
205
206 ############################################################################
207
208 # apache2 methods...
209
210 # removes a config file for apache given the app name and site name.
211 function remove_apache_config()
212 {
213   local sitename="$1"; shift
214
215   local site_config="/etc/apache2/sites-available/${sitename}.conf"
216
217   if [ -f "$site_config" ]; then
218     # don't destroy, just shuffle.
219     \mv -f "$site_config" "/tmp/$(basename ${site_config})-old-${RANDOM}"
220     test_or_die "removing site config: $site_config"
221   else
222     echo "Did not see a site config to remove: $site_config"
223   fi
224 }
225
226 # this function writes out the new configuration file for the site.
227 function write_apache_config()
228 {
229   local appname="$1"; shift
230   local sitename="$1"; shift
231   local site_path="$1"; shift
232
233   local site_config="/etc/apache2/sites-available/${sitename}.conf"
234
235   # check if config file already exists and bail if so.
236   if [ -f "$site_config" ]; then
237     echo "The apache configuration file already exists at:"
238     echo "  $site_config"
239     echo "Since apache configuration files can get very complex, we do not want to"
240     echo "assume that this file is removable.  Calling the site addition done."
241     exit 0
242   fi
243
244   echo "Creating a new apache2 site for $sitename with config file:"
245   echo "  $site_config"
246
247   # if no path, then we default to our standard app storage location.  otherwise, we
248   # put the site where they told us to.
249   if [ -z "$site_path" ]; then
250     # path where site gets checked out, in some arcane manner, and which happens to be
251     # above the path where we put webroot (in the storage suffix, if defined).
252     local path_above="${BASE_APPLICATION_PATH}/${appname}"
253     # no slash between appname and suffix, in case suffix is empty.
254     local full_path="${path_above}${STORAGE_SUFFIX}"
255 #echo really full path is $full_path
256   else
257     # we'll go with their specification for the site storage.
258     local full_path="$site_path"
259   fi
260
261   echo "
262 # set up the user's web folder as an apache user web directory.
263
264 # set permissions on the actual app folder.
265 <Directory \"$full_path\">
266   Options +ExecCGI +Indexes +FollowSymLinks +Includes +MultiViews 
267   Require all granted
268 </Directory>
269
270 <VirtualHost *:80>
271     ServerName ${sitename}
272     DocumentRoot ${full_path}
273     ErrorLog \${APACHE_LOG_DIR}/${sitename}-error.log
274     CustomLog \${APACHE_LOG_DIR}/${sitename}-access.log combined
275     Include /etc/apache2/conf-library/basic-options.conf
276     Include /etc/apache2/conf-library/rewrite-enabling.conf
277 </VirtualHost>
278 " >"$site_config" 
279
280   chown "$(logname):$(logname)" "$site_config"
281   test_or_die "setting ownership on: $site_config"
282 }
283
284 # stops apache from serving up the site.
285 function disable_site()
286 {
287   local sitename="$1"; shift
288   local site_config="/etc/apache2/sites-available/${sitename}.conf"
289
290   if [ ! -f "$site_config" ]; then
291     echo "The site config did not exist and could not be disabled: $site_config"
292     return 0
293   fi
294
295 #hmmm: repeated pattern of hidden output file, very useful.  abstract it...
296   local outfile="$TMP/apacheout.$RANDOM"
297   a2dissite "$(basename $site_config)" &>$outfile
298   if [ $? -ne 0 ]; then
299     # an error happened, so we show the command's output at least.
300     cat $outfile
301     echo
302     echo "There was a problem disabling the apache config file in:"
303     echo "  $site_config"
304     echo "Please consult the apache error logs for more details."
305     exit 1
306   fi
307   \rm "$outfile"
308 }
309
310 # turns on the config file we create above for apache.
311 function enable_site()
312 {
313   local sitename="$1"; shift
314   local site_config="/etc/apache2/sites-available/${sitename}.conf"
315
316   local outfile="$TMP/apacheout.$RANDOM"
317   a2ensite "$(basename $site_config)" &>$outfile
318   if [ $? -ne 0 ]; then
319     # an error happened, so we show the command's output at least.
320     cat $outfile
321     echo
322     echo "There was a problem enabling the apache config file in:"
323     echo "  $site_config"
324     echo "Please consult the apache error logs for more details."
325     exit 1
326   fi
327   \rm "$outfile"
328 }
329
330 # restarts the apache2 service.
331 function restart_apache()
332 {
333   service apache2 restart
334   if [ $? -ne 0 ]; then
335     echo "There was a problem restarting the apache2 service."
336     echo "Please consult the apache error logs for more details."
337     exit 1
338   fi
339   echo Apache2 service restarted.
340 }
341
342 # sets up the serverpilot storage location for a user hosted web site.
343 function maybe_create_site_storage()
344 {
345   local our_app="$1"; shift
346   # make sure the path for storage this app exists for the user.
347   local full_path="$BASE_APPLICATION_PATH/$our_app"
348   if [ ! -d "$full_path" ]; then
349     mkdir -p $full_path
350     test_or_die "The app storage path could not be created.\n  Path in question is: $full_path"
351   fi
352
353   # now give the web server some access to the folder.  this is crucial since the folders
354   # can be hosted in any user folder, and the group permissions will not necessarily be correct already.
355   local chow_path="$full_path"
356   # only the first chmod is recursive; the rest just apply to the specific folder of interest.
357   chmod -R g+rx "$chow_path"
358   # walk backwards up the path and fix perms.
359   while [[ $chow_path != $HOME ]]; do
360 #echo chow path is now $chow_path
361     chmod g+rx "$chow_path"
362     test_or_die "Failed to add group permissions on the path: $chow_path"
363     # reassert the user's ownership of any directories we might have just created.
364     chown $(logname) "$chow_path"
365     test_or_die "changing ownership to user failed on the path: $chow_path"
366     chow_path="$(dirname "$chow_path")"
367   done
368 }
369
370 ############################################################################
371
372