- If specified should contain a value for x-transip-mail-auth.
90 | This is the value which can be found in TransIP dashboard.
91 | TransIP requires this to be added for every domain.
92 |
93 | If omitted the script won't verify the value of the record
94 | in DNS. Any value will give a positive result.
95 |
96 | --debug - Print DEBUG output
97 | --verbose - Do a verbose output
98 |
99 | --dry-run - Do selected tests without writing changes to a file
100 |
101 | Important:
102 |
103 | You can add excluded domains in the file ${EXCLUDED_LIST}
104 | Verified domains will be added in the file ${LIST_FILE}
105 | Nothing else gets changed by the script.
106 |
107 |
108 | The script uses remote DNS resolver ${DNS_RESOLVER}.
109 | Make sure the server's firewall does not block connections to it.
110 |
111 | Copyright:
112 |
113 | (c) 2022 Alex Grebenschikov, www.poralix.com
114 |
115 | License:
116 |
117 | MIT License
118 | ";
119 | exit 0;
120 | }
121 |
122 | c_echo()
123 | {
124 | [ "${VERBOSE}" == "1" ] && echo "${1}";
125 | }
126 |
127 | do_add_domain()
128 | {
129 | if [ "${DRY_RUN}" == "1" ]; then
130 | DRY_RUN_DOMAINS="${1}\n${DRY_RUN_DOMAINS}";
131 | else
132 | echo "${1}" >> "${LIST_FILE}.new";
133 | fi;
134 | }
135 |
136 | for ARG in $@;
137 | do
138 | case "${ARG}" in
139 | --debug)
140 | DEBUG=1;
141 | ;;
142 | --key=*)
143 | AUTH_KEY=$(echo ${ARG} | cut -d= -f2);
144 | ;;
145 | --verbose)
146 | VERBOSE=1;
147 | ;;
148 | --dry-run)
149 | DRY_RUN=1;
150 | ;;
151 | --test-spf)
152 | TEST_SPF=1;
153 | ;;
154 | --test-dkim)
155 | TEST_DKIM=1;
156 | ;;
157 | --test-all)
158 | TEST_AUTH=1;
159 | TEST_SPF=1;
160 | TEST_DKIM=1;
161 | ;;
162 | --run)
163 | RUN=1;
164 | ;;
165 | --help|--usage|*)
166 | do_usage;
167 | ;;
168 | esac;
169 | done;
170 |
171 | [ -z "$1" ] && do_usage;
172 |
173 | DOMAINS="";
174 |
175 | [ -h "${LIST_FILE}" ] && echo "[ERROR] The ${LIST_FILE} is a symbolic link. Terminating..." && exit 1;
176 | [ ! -s "${DOMAINS_FILE}" ] && echo "[ERROR] Could not find a list of domains. Terminating..." && exit 2;
177 |
178 | [ -s "${LIST_FILE}" ] && cp -p "${LIST_FILE}" "${LIST_FILE}.old";
179 | [ -f "${LIST_FILE}.new" ] && rm -f "${LIST_FILE}.new";
180 |
181 | touch "${LIST_FILE}.new";
182 | chmod 600 "${LIST_FILE}.new";
183 |
184 | AUTH_OK_DOMAINS="";
185 | SPF_OK_DOMAINS="";
186 | DKIM_OK_DOMAINS="";
187 | FOUND_OK_DOMAINS="";
188 | DRY_RUN_DOMAINS="";
189 |
190 | c_echo "STEP 1: Testing ${SEARCH_RECORD} record";
191 | c_echo "====================================================================";
192 |
193 | for DOMAIN in $(cat "${DOMAINS_FILE}" | sort | uniq);
194 | do
195 | c_echo "[OK] Processing ${DOMAIN}";
196 |
197 | [ "${DEBUG}" == "1" ] && set -x;
198 |
199 | if [ -z "${AUTH_KEY}" ]; then
200 | CHECK_AUTH_RECORD=$(dig +short TXT "${SEARCH_RECORD}.${DOMAIN}" @${DNS_RESOLVER} | xargs);
201 | else
202 | CHECK_AUTH_RECORD=$(dig +short TXT "${SEARCH_RECORD}.${DOMAIN}" @${DNS_RESOLVER} | grep "${AUTH_KEY}");
203 | fi;
204 |
205 | if [ -z "${CHECK_AUTH_RECORD}" ]; then
206 | c_echo "[WARNING] Domain ${DOMAIN} is not configured to use TransIP mail service. AUTH record is missing.";
207 | else
208 | c_echo "[INFO][${DOMAIN}] Found a value ${CHECK_AUTH_RECORD} for ${SEARCH_RECORD}.${DOMAIN} in DNS.";
209 | AUTH_OK_DOMAINS="${AUTH_OK_DOMAINS} ${DOMAIN}";
210 | fi;
211 |
212 | [ "${DEBUG}" == "1" ] && set +x;
213 | c_echo "--------------------------------------------------------------------";
214 | done;
215 |
216 | # SHOULD WE TEST SPF?
217 | if [ "${TEST_SPF}" == "1" ]; then
218 | c_echo "";
219 | c_echo "STEP 2: Testing SPF record";
220 | c_echo "====================================================================";
221 |
222 | if [ -n "${AUTH_OK_DOMAINS}" ]; then
223 | TEST_DOMAINS="${AUTH_OK_DOMAINS}";
224 | else
225 | TEST_DOMAINS=$(cat "${DOMAINS_FILE}" | sort | uniq);
226 | fi;
227 |
228 | for DOMAIN in ${TEST_DOMAINS};
229 | do
230 | CHECK_SPF_RECORD=$(dig +short TXT "${DOMAIN}" @${DNS_RESOLVER} | grep -o " include:_spf.transip.email ");
231 |
232 | if [ -z "${CHECK_SPF_RECORD}" ]; then
233 | c_echo "[WARNING] Domain ${DOMAIN} is not configured to use TransIP mail service. SPF record is bad.";
234 | else
235 | c_echo "[INFO][${DOMAIN}] Found a string ${CHECK_SPF_RECORD// /} in SPF record for ${DOMAIN} in DNS.";
236 | SPF_OK_DOMAINS="${SPF_OK_DOMAINS} ${DOMAIN}";
237 | fi;
238 | c_echo "--------------------------------------------------------------------";
239 | done;
240 | fi;
241 |
242 | # SHOULD WE TEST DKIM?
243 | if [ "${TEST_DKIM}" == "1" ]; then
244 | c_echo "";
245 | c_echo "STEP 3: Testing DKIM record";
246 | c_echo "====================================================================";
247 |
248 | if [ -n "${SPF_OK_DOMAINS}" ]; then
249 | TEST_DOMAINS="${SPF_OK_DOMAINS}";
250 | elif [ -n "${AUTH_OK_DOMAINS}" ]; then
251 | TEST_DOMAINS="${AUTH_OK_DOMAINS}";
252 | else
253 | TEST_DOMAINS=$(cat "${DOMAINS_FILE}" | sort | uniq);
254 | fi;
255 |
256 | for DOMAIN in ${TEST_DOMAINS};
257 | do
258 | CHECK_DKIM_A_RECORD=$(dig +short CNAME "transip-A._domainkey.${DOMAIN}" @${DNS_RESOLVER} | grep "_dkim-A.transip.email");
259 | CHECK_DKIM_B_RECORD=$(dig +short CNAME "transip-B._domainkey.${DOMAIN}" @${DNS_RESOLVER} | grep "_dkim-B.transip.email");
260 | CHECK_DKIM_C_RECORD=$(dig +short CNAME "transip-C._domainkey.${DOMAIN}" @${DNS_RESOLVER} | grep "_dkim-C.transip.email");
261 |
262 | if [ -z "${CHECK_DKIM_A_RECORD}" ] || [ -z "${CHECK_DKIM_B_RECORD}" ] || [ -z "${CHECK_DKIM_C_RECORD}" ]; then
263 | c_echo "[WARNING] Domain ${DOMAIN} is not configured to use TransIP mail service. DKIM record is bad.";
264 | else
265 | c_echo "[INFO][${DOMAIN}] Found DKIM record ${CHECK_DKIM_A_RECORD} for ${DOMAIN} in DNS.";
266 | c_echo "[INFO][${DOMAIN}] Found DKIM record ${CHECK_DKIM_B_RECORD} for ${DOMAIN} in DNS.";
267 | c_echo "[INFO][${DOMAIN}] Found DKIM record ${CHECK_DKIM_C_RECORD} for ${DOMAIN} in DNS.";
268 | DKIM_OK_DOMAINS="${DKIM_OK_DOMAINS} ${DOMAIN}";
269 | fi;
270 | c_echo "--------------------------------------------------------------------";
271 | done;
272 | fi;
273 |
274 | if [ "${TEST_DKIM}" == "1" ]; then
275 | FOUND_OK_DOMAINS="${DKIM_OK_DOMAINS}";
276 | elif [ "${TEST_DKIM}" == "0" ] && [ "${TEST_SPF}" == "1" ]; then
277 | FOUND_OK_DOMAINS="${SPF_OK_DOMAINS}";
278 | elif [ "${TEST_DKIM}" == "0" ] && [ "${TEST_SPF}" == "0" ]; then
279 | FOUND_OK_DOMAINS="${AUTH_OK_DOMAINS}";
280 | fi;
281 |
282 | if [ -n "${FOUND_OK_DOMAINS}" ]; then
283 |
284 | c_echo "";
285 | c_echo "STEP 4: Completing the list of domains";
286 | c_echo "====================================================================";
287 |
288 | for DOMAIN in ${FOUND_OK_DOMAINS};
289 | do
290 | if [ -s "${EXCLUDED_LIST}" ]; then
291 | c_echo "[INFO] Found ${EXCLUDED_LIST}";
292 | CHECK_EXCLUDED=$(grep "^${DOMAIN}$" "${EXCLUDED_LIST}");
293 | if [ -z "${CHECK_EXCLUDED}" ]; then
294 | do_add_domain "${DOMAIN}";
295 | else
296 | c_echo "[WARNING] Skipping domain ${DOMAIN}, as it is listed in ${EXCLUDED_LIST}"
297 | fi;
298 | else
299 | do_add_domain "${DOMAIN}";
300 | fi;
301 | c_echo "--------------------------------------------------------------------";
302 | done;
303 | else
304 | echo "[WARNING] None of the hosted domains is configured for sending over TransIP";
305 | fi;
306 |
307 | if [ "${DRY_RUN}" == "0" ]; then
308 |
309 | if [ -f "${LIST_FILE}.new" ]; then
310 | cat "${LIST_FILE}.new" > "${LIST_FILE}";
311 | rm -f "${LIST_FILE}.new";
312 | fi;
313 |
314 | chown root:mail "${LIST_FILE}";
315 | chmod 640 "${LIST_FILE}";
316 |
317 | echo -e "\n\n====================================================================";
318 | echo " Listed the following domains in ${LIST_FILE}";
319 | echo "====================================================================";
320 | cat "${LIST_FILE}"
321 | echo -e "====================================================================";
322 | wc -l "${LIST_FILE}";
323 | echo -e "\n";
324 | else
325 | echo -e "\n\n================================================================================";
326 | echo " Found the following domains to be listed in ${LIST_FILE}";
327 | echo "================================================================================";
328 | echo -n -e "${DRY_RUN_DOMAINS}" | sort | grep -v "$^";
329 | echo -e "================================================================================";
330 | echo -n -e "${DRY_RUN_DOMAINS}" | grep -v "$^" | wc -l;
331 | echo -e "\n";
332 | fi;
333 |
334 | exit 0;
335 |
--------------------------------------------------------------------------------
/hooks/README.md:
--------------------------------------------------------------------------------
1 | # Directadmin hooks: custom PRE and POST action scripts
2 |
3 | Directadmin allows to run custom scripts before and after a certain action performed by the control panel.
4 | So called hooks, or hookable events are custom PRE and POST action scripts. Here you can find a list of all custom scripts.
5 |
6 | The hook scripts:
7 |
8 | - [PRE action hooks are executed before an action in DirectAdmin](hooks_pre.md)
9 | - [POST action hooks are executed after an action in DirectAdmin](hooks_post.md)
10 |
11 | # Additional information
12 |
13 | - [Ability to pass custom variables to pre/post.sh scripts from GET/POST](https://www.directadmin.com/features.php?id=1780)
14 | - [Tool that will run custom scripts for base features](https://www.directadmin.com/features.php?id=183)
15 |
--------------------------------------------------------------------------------
/hooks/hooks_post.md:
--------------------------------------------------------------------------------
1 | - all_backups_post.sh
2 | - all_post.sh
3 | - all_restores_post.sh
4 | - autoresponder_set_post.sh
5 | - check_letsencrypt_expiries_post.sh
6 | - check_partitions_notice_post.sh
7 | - cron_set_post.sh
8 | - database_create_post.sh
9 | - database_delete_post.sh
10 | - database_user_create_post.sh
11 | - database_user_destroy_post.sh
12 | - database_user_password_change_post.sh
13 | - dkim_create_post.sh
14 | - dns_create_post.sh
15 | - dns_delete_post.sh
16 | - dns_raw_save_post.sh
17 | - dnssec_sign_post.sh
18 | - dns_write_post.sh
19 | - domain_change_post.sh
20 | - domain_create_post.sh
21 | - domain_destroy_post.sh
22 | - domain_modify_post.sh
23 | - domain_pointer_create_post.sh
24 | - domain_pointer_destroy_post.sh
25 | - email_change_pass_post.sh
26 | - email_create_post.sh
27 | - email_destroy_post.sh
28 | - email_filter_write_post.sh
29 | - file_manager_upload_post.sh
30 | - forwarder_create_post.sh
31 | - forwarder_delete_post.sh
32 | - ftp_delete_post.sh
33 | - ip_change_post.sh
34 | - ipsconf_write_post.sh
35 | - letsencrypt_post.sh
36 | - load_spike_notice_post.sh
37 | - named_action_post.sh
38 | - openlitespeed_ips_conf_write_post.sh
39 | - openlitespeed_listeners_write_post.sh
40 | - overusage_notice_post.sh
41 | - public_html_link_set_post.sh
42 | - reseller_modify_post.sh
43 | - spam_script_chmod_0_post.sh
44 | - ssl_save_post.sh
45 | - subdomain_create_post.sh
46 | - subdomain_destroy_post.sh
47 | - tally_post.sh
48 | - tally_rotation_post.sh
49 | - tally_user_post.sh
50 | - taskq_dns_post.sh
51 | - update_post.sh
52 | - user_activate_post.sh
53 | - user_backup_post.sh
54 | - user_create_post.sh
55 | - user_destroy_post.sh
56 | - user_httpd_write_post.sh
57 | - user_info_modify_post.sh
58 | - user_modify_post.sh
59 | - user_password_change_post.sh
60 | - user_restore_fail_post.sh
61 | - user_restore_post.sh
62 | - user_suspend_post.sh
63 | - vacation_set_post.sh
64 |
--------------------------------------------------------------------------------
/hooks/hooks_pre.md:
--------------------------------------------------------------------------------
1 | - all_backups_pre.sh
2 | - all_pre.sh
3 | - autoresponder_delete_pre.sh
4 | - autoresponder_set_pre.sh
5 | - backup_save_pre.sh
6 | - brute_force_notify_pre.sh
7 | - cron_set_pre.sh
8 | - database_create_pre.sh
9 | - database_delete_pre.sh
10 | - database_user_password_change_pre.sh
11 | - domain_change_pre.sh
12 | - domain_create_pre.sh
13 | - domain_destroy_pre.sh
14 | - domain_modify_pre.sh
15 | - domain_pointer_create_pre.sh
16 | - domain_pointer_destroy_pre.sh
17 | - email_change_pass_pre.sh
18 | - email_create_pre.sh
19 | - email_destroy_pre.sh
20 | - email_filter_write_pre.sh
21 | - filemanager_pre.sh
22 | - forwarder_create_pre.sh
23 | - forwarder_delete_pre.sh
24 | - ip_change_pre.sh
25 | - letsencrypt_pre.sh
26 | - load_spike_notice_pre.sh
27 | - lost_password_pre.sh
28 | - overusage_notice_pre.sh
29 | - public_html_link_set_pre.sh
30 | - reseller_destroy_pre.sh
31 | - reseller_modify_pre.sh
32 | - sendmail_pre.sh
33 | - session_destroy_pre.sh
34 | - ssl_save_pre.sh
35 | - subdomain_create_pre.sh
36 | - subdomain_destroy_pre.sh
37 | - tally_pre.sh
38 | - user_activate_pre.sh
39 | - user_backup_compress_pre.sh
40 | - user_backup_pre.sh
41 | - user_create_pre.sh
42 | - user_destroy_pre.sh
43 | - user_httpd_write_pre.sh
44 | - user_modify_pre.sh
45 | - user_password_change_pre.sh
46 | - user_restore_pre.sh
47 | - user_suspend_pre.sh
48 | - vacation_set_pre.sh
49 |
--------------------------------------------------------------------------------
/letsencrypt/README.md:
--------------------------------------------------------------------------------
1 | # A script to force Let's Encrypt to use DST Root CA X3
2 |
3 | Here is a patch for Let's Encrypt script from DirectAdmin to force it to use "DST Root CA X3" instead of "ISRG Root X1" when issuing SSL certificates.
4 |
5 | For installation run as root:
6 |
7 | ```
8 | mkdir -p /usr/local/directadmin/custombuild/custom/hooks/letsencrypt/post/
9 | cd /usr/local/directadmin/custombuild/custom/hooks/letsencrypt/post/
10 | wget -O poralix_patch_chain.sh https://raw.githubusercontent.com/poralix/directadmin-utils/master/letsencrypt/poralix_patch_chain.sh
11 | chmod 750 poralix_patch_chain.sh
12 | /usr/local/directadmin/custombuild/build letsencrypt
13 | ```
14 |
15 |
16 | # let's encrypt patch for VERSION=1.0.18 letsencrypt.sh
17 |
18 | Having 10-20-30... domains (and more) in ca.san_config is a challenge to get them verified at once. This patch will give you a re-try on challenge verification.
19 |
20 | # Install
21 |
22 | ```
23 | cd /usr/local/directadmin/scripts
24 | cp -p letsencrypt.sh letsencrypt_poralix.sh
25 | wget -O ./letsencrypt_poralix.patch https://raw.githubusercontent.com/poralix/directadmin-utils/master/letsencrypt/letsencrypt_poralix.patch
26 | patch ./letsencrypt_poralix.sh -i letsencrypt_poralix.patch
27 | ```
28 |
29 | # Example:
30 |
31 | ```
32 | Getting challenge for mail.poralix.com from acme-server...
33 | Challenge error: HTTP/1.1 100 Continue
34 | Expires: Tue, 11 Apr 2017 04:21:31 GMT
35 | Cache-Control: max-age=0, no-cache, no-store
36 | Pragma: no-cache
37 |
38 | HTTP/1.1 500 Internal Server Error
39 | Server: AkamaiGHost
40 | Mime-Version: 1.0
41 | Content-Type: text/html
42 | Content-Length: 176
43 | Expires: Tue, 11 Apr 2017 04:21:31 GMT
44 | Cache-Control: max-age=0, no-cache, no-store
45 | Pragma: no-cache
46 | Date: Tue, 11 Apr 2017 04:21:31 GMT
47 | Connection: close
48 |
49 | Error
50 | An error occurred while processing your request.
51 | Reference #179.8c346d68.1491884491.2960089
52 | .
53 |
54 | Do you want to retry (yes/no): yes
55 | Waiting for domain verification...
56 | Challenge is valid.
57 | ```
58 |
59 | That's it!
60 |
--------------------------------------------------------------------------------
/letsencrypt/autoletsencrypt.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | VERSION=1.2
3 | WELLKNOWN_PATH="/var/www/html/.well-known/acme-challenge"
4 | TIMESTAMP=`date +%s`
5 | CURL=/usr/local/bin/curl
6 | if [ ! -x ${CURL} ]; then
7 | CURL=/usr/bin/curl
8 | fi
9 |
10 | challenge_check() {
11 | if [ ! -d ${WELLKNOWN_PATH} ]; then
12 | mkdir -p ${WELLKNOWN_PATH}
13 | fi
14 | touch ${WELLKNOWN_PATH}/letsencrypt_${TIMESTAMP}
15 | #Checking if http://www.domain.com/.well-known/acme-challenge/letsencrypt_${TIMESTAMP} is available
16 | if ! ${CURL} ${CURL_OPTIONS} -k -I -L -X GET http://${1}/.well-known/acme-challenge/letsencrypt_${TIMESTAMP} 2>/dev/null | grep -m1 -q 'HTTP.*200'; then
17 | echo 1
18 | else
19 | echo 0
20 | fi
21 | rm -f ${WELLKNOWN_PATH}/letsencrypt_${TIMESTAMP}
22 | }
23 |
24 | for u in `ls /usr/local/directadmin/data/users`; do
25 | {
26 | for d in `cat /usr/local/directadmin/data/users/$u/domains.list`; do
27 | {
28 | if [ ! -e /usr/local/directadmin/data/users/$u/domains/$d.cert ] && [ -s /usr/local/directadmin/data/users/$u/domains/$d.conf ]; then
29 | CHALLENGE_TEST=`challenge_check $d`
30 | if [ ${CHALLENGE_TEST} -ne 1 ]; then
31 | CHALLENGE_TEST2=`challenge_check www.$d`
32 | if [ ${CHALLENGE_TEST2} -ne 1 ]; then
33 | /usr/local/directadmin/scripts/letsencrypt.sh request ${d} 4096
34 | else
35 | /usr/local/directadmin/scripts/letsencrypt.sh request_single ${d} 4096
36 | fi
37 | fi
38 | fi
39 | if [ -e /usr/local/directadmin/data/users/$u/domains/$d.cert ]; then
40 | REWRITE=false
41 | if ! grep -m1 -q '^ssl=ON' /usr/local/directadmin/data/users/$u/domains/$d.conf; then
42 | perl -pi -e 's|^ssl\=OFF|ssl=ON|g' /usr/local/directadmin/data/users/$u/domains/$d.conf
43 | REWRITE=true
44 | fi
45 | if ! grep -m1 -q '^SSLCACertificateFile=' /usr/local/directadmin/data/users/$u/domains/$d.conf; then
46 | perl -pi -e "s|^UseCanonicalName=|SSLCACertificateFile=/usr/local/directadmin/data/users/$u/domains/$d.cacert\nSSLCertificateFile=/usr/local/directadmin/data/users/$u/domains/$d.cert\nSSLCertificateKeyFile=/usr/local/directadmin/data/users/$u/domains/$d.key\nUseCanonicalName=|g" /usr/local/directadmin/data/users/$u/domains/$d.conf
47 | REWRITE=true
48 | fi
49 | if ${REWRITE}; then
50 | echo "action=rewrite&value=httpd&user=$u" >> /usr/local/directadmin/data/task.queue
51 | fi
52 | fi
53 | }
54 | done;
55 | }
56 | done;
57 | exit 0
58 |
--------------------------------------------------------------------------------
/letsencrypt/autoletsencrypt.sh.patch:
--------------------------------------------------------------------------------
1 | --- autoletsencrypt.sh 2018-07-05 05:29:48.000000000 +0700
2 | +++ autoletsencrypt_mail.sh 2019-01-12 15:06:06.000000000 +0700
3 | @@ -1,5 +1,23 @@
4 | #!/bin/sh
5 | -VERSION=1.2
6 | +VERSION=1.2.patched
7 | +###############################################################################
8 | +# #
9 | +# Automatically setup LetsEncrypt SSL for *all* domains #
10 | +# that do not currently have a certificate #
11 | +# #
12 | +###############################################################################
13 | +# #
14 | +# Original script written by Directadmin #
15 | +# https://help.directadmin.com/item.php?id=675 #
16 | +# http://files.directadmin.com/services/all/letsencrypt/autoletsencrypt.sh #
17 | +# #
18 | +###############################################################################
19 | +# #
20 | +# Patched by Poralix to add mail subdomain into certs #
21 | +# Last modified: Sat Jan 12 15:04:00 +07 2019 (support@poralix.com) #
22 | +# #
23 | +###############################################################################
24 | +
25 | WELLKNOWN_PATH="/var/www/html/.well-known/acme-challenge"
26 | TIMESTAMP=`date +%s`
27 | CURL=/usr/local/bin/curl
28 | @@ -29,7 +47,10 @@
29 | CHALLENGE_TEST=`challenge_check $d`
30 | if [ ${CHALLENGE_TEST} -ne 1 ]; then
31 | CHALLENGE_TEST2=`challenge_check www.$d`
32 | - if [ ${CHALLENGE_TEST2} -ne 1 ]; then
33 | + CHALLENGE_TEST3=`challenge_check mail.$d`
34 | + if [ ${CHALLENGE_TEST2} -ne 1 ] && [ ${CHALLENGE_TEST3} -ne 1 ]; then
35 | + /usr/local/directadmin/scripts/letsencrypt.sh request ${d},www.${d},mail.${d} 4096
36 | + elif [ ${CHALLENGE_TEST2} -ne 1 ]; then
37 | /usr/local/directadmin/scripts/letsencrypt.sh request ${d} 4096
38 | else
39 | /usr/local/directadmin/scripts/letsencrypt.sh request_single ${d} 4096
40 |
--------------------------------------------------------------------------------
/letsencrypt/autoletsencrypt_mail.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | VERSION=1.2.patched
3 | ###############################################################################
4 | # #
5 | # Automatically setup LetsEncrypt SSL for *all* domains #
6 | # that do not currently have a certificate #
7 | # #
8 | ###############################################################################
9 | # #
10 | # Original script written by Directadmin #
11 | # https://help.directadmin.com/item.php?id=675 #
12 | # http://files.directadmin.com/services/all/letsencrypt/autoletsencrypt.sh #
13 | # #
14 | ###############################################################################
15 | # #
16 | # Patched by Poralix to add mail subdomain into certs #
17 | # Last modified: Sat Jan 12 15:04:00 +07 2019 (support@poralix.com) #
18 | # #
19 | ###############################################################################
20 |
21 | WELLKNOWN_PATH="/var/www/html/.well-known/acme-challenge"
22 | TIMESTAMP=`date +%s`
23 | CURL=/usr/local/bin/curl
24 | if [ ! -x ${CURL} ]; then
25 | CURL=/usr/bin/curl
26 | fi
27 |
28 | challenge_check() {
29 | if [ ! -d ${WELLKNOWN_PATH} ]; then
30 | mkdir -p ${WELLKNOWN_PATH}
31 | fi
32 | touch ${WELLKNOWN_PATH}/letsencrypt_${TIMESTAMP}
33 | #Checking if http://www.domain.com/.well-known/acme-challenge/letsencrypt_${TIMESTAMP} is available
34 | if ! ${CURL} ${CURL_OPTIONS} -k -I -L -X GET http://${1}/.well-known/acme-challenge/letsencrypt_${TIMESTAMP} 2>/dev/null | grep -m1 -q 'HTTP.*200'; then
35 | echo 1
36 | else
37 | echo 0
38 | fi
39 | rm -f ${WELLKNOWN_PATH}/letsencrypt_${TIMESTAMP}
40 | }
41 |
42 | for u in `ls /usr/local/directadmin/data/users`; do
43 | {
44 | for d in `cat /usr/local/directadmin/data/users/$u/domains.list`; do
45 | {
46 | if [ ! -e /usr/local/directadmin/data/users/$u/domains/$d.cert ] && [ -s /usr/local/directadmin/data/users/$u/domains/$d.conf ]; then
47 | CHALLENGE_TEST=`challenge_check $d`
48 | if [ ${CHALLENGE_TEST} -ne 1 ]; then
49 | CHALLENGE_TEST2=`challenge_check www.$d`
50 | CHALLENGE_TEST3=`challenge_check mail.$d`
51 | if [ ${CHALLENGE_TEST2} -ne 1 ] && [ ${CHALLENGE_TEST3} -ne 1 ]; then
52 | /usr/local/directadmin/scripts/letsencrypt.sh request ${d},www.${d},mail.${d} 4096
53 | elif [ ${CHALLENGE_TEST2} -ne 1 ]; then
54 | /usr/local/directadmin/scripts/letsencrypt.sh request ${d} 4096
55 | else
56 | /usr/local/directadmin/scripts/letsencrypt.sh request_single ${d} 4096
57 | fi
58 | fi
59 | fi
60 | if [ -e /usr/local/directadmin/data/users/$u/domains/$d.cert ]; then
61 | REWRITE=false
62 | if ! grep -m1 -q '^ssl=ON' /usr/local/directadmin/data/users/$u/domains/$d.conf; then
63 | perl -pi -e 's|^ssl\=OFF|ssl=ON|g' /usr/local/directadmin/data/users/$u/domains/$d.conf
64 | REWRITE=true
65 | fi
66 | if ! grep -m1 -q '^SSLCACertificateFile=' /usr/local/directadmin/data/users/$u/domains/$d.conf; then
67 | perl -pi -e "s|^UseCanonicalName=|SSLCACertificateFile=/usr/local/directadmin/data/users/$u/domains/$d.cacert\nSSLCertificateFile=/usr/local/directadmin/data/users/$u/domains/$d.cert\nSSLCertificateKeyFile=/usr/local/directadmin/data/users/$u/domains/$d.key\nUseCanonicalName=|g" /usr/local/directadmin/data/users/$u/domains/$d.conf
68 | REWRITE=true
69 | fi
70 | if ${REWRITE}; then
71 | echo "action=rewrite&value=httpd&user=$u" >> /usr/local/directadmin/data/task.queue
72 | fi
73 | fi
74 | }
75 | done;
76 | }
77 | done;
78 | exit 0
79 |
--------------------------------------------------------------------------------
/letsencrypt/fix_le_caroot.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # A SCRIPT TO REWRITE EXPIRED LET'S ENCRYPT CAROOT CERTIFICATE
4 | # =====================================================================
5 | # Solving the error:
6 | # depth=3 O = Digital Signature Trust Co., CN = DST Root CA X3
7 | # verify error:num=10:certificate has expired
8 | # notAfter=Sep 30 14:01:15 2021 GMT
9 | # =====================================================================
10 | # Writen by Alex S Grebenschikov $ Sun Oct 3 21:20:59 +07 2021
11 | # www.poralix.com
12 | # =====================================================================
13 |
14 | print_cert()
15 | {
16 | echo '-----BEGIN CERTIFICATE-----
17 | MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
18 | TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
19 | cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
20 | WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
21 | RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
22 | AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
23 | R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
24 | sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
25 | NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
26 | Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
27 | /kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
28 | AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
29 | Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
30 | FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
31 | AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
32 | Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
33 | gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
34 | PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
35 | ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
36 | CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
37 | lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
38 | avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
39 | yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
40 | yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
41 | hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
42 | HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
43 | MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
44 | nLRbwHOoq7hHwg==
45 | -----END CERTIFICATE-----';
46 | }
47 |
48 |
49 | for DOM in $(cat /etc/virtual/domainowners | cut -d\: -f1);
50 | do
51 | USER=$(grep ^${DOM}: /etc/virtual/domainowners | awk '{print $2}');
52 | if [ -f "/usr/local/directadmin/data/users/${USER}/domains/${DOM}.cert.creation_time" ];
53 | then
54 | echo "Updating ${DOM} owned by ${USER}";
55 | print_cert > "/usr/local/directadmin/data/users/${USER}/domains/${DOM}.cacert";
56 | cat "/usr/local/directadmin/data/users/${USER}/domains/${DOM}.cert" "/usr/local/directadmin/data/users/${USER}/domains/${DOM}.cacert" > "/usr/local/directadmin/data/users/${USER}/domains/${DOM}.cert.combined";
57 | fi;
58 | done;
59 |
60 | cd /usr/local/directadmin/custombuild/;
61 | ./build rewrite_confs;
62 |
63 | exit;
64 |
--------------------------------------------------------------------------------
/letsencrypt/letsencrypt_poralix-1.0.18.patch:
--------------------------------------------------------------------------------
1 | --- /usr/local/directadmin/scripts/letsencrypt.sh 2017-11-15 23:43:21.000000000 +0700
2 | +++ /usr/local/directadmin/scripts/letsencrypt_poralix.sh 2017-11-16 15:09:26.000000000 +0700
3 | @@ -443,6 +443,16 @@
4 | echo "Getting challenge for ${single_domain} from acme-server..."
5 | send_signed_request "normal" "${API}/acme/new-authz" '{"resource": "new-authz", "identifier": {"type": "dns", "value": "'"${single_domain}"'"}}'
6 |
7 | + # poralix
8 | + if [ "${HTTP_STATUS}" -ne 201 ] ; then
9 | + sleep 1;
10 | + ERROR500=$(echo ${RESPONSE} | grep -c 'HTTP/1.1 500 Internal Server Error');
11 | + if [ "${ERROR500}" -ne 0 ]; then
12 | + echo "Error 500 occured in authz request: ${RESPONSE}. Trying once again...";
13 | + send_signed_request "normal" "${API}/acme/new-authz" '{"resource": "new-authz", "identifier": {"type": "dns", "value": "'"${single_domain}"'"}}';
14 | + fi;
15 | + fi;
16 | +
17 | #Account has a key for let's encrypt, but it's not registered
18 | if [ "${HTTP_STATUS}" -eq 403 ] ; then
19 | echo "User let's encrypt key has been found, but not registered. Registering..."
20 | @@ -535,6 +545,14 @@
21 | echo "Challenge is ${CHALLENGE_STATUS}. Details: ${CHALLENGE_DETAIL}. Exiting..."
22 | exit 1
23 | fi
24 | +
25 | + # poralix
26 | + echo -n "Sleep some ";
27 | + for n in `seq 1 5`; do
28 | + sleep 1;
29 | + echo -n '.';
30 | + done;
31 | + echo '';
32 | }
33 | done
34 |
35 |
--------------------------------------------------------------------------------
/letsencrypt/letsencrypt_poralix-1.0.8.patch:
--------------------------------------------------------------------------------
1 | --- /usr/local/directadmin/scripts/letsencrypt.sh 2017-03-28 19:07:21.000000000 +1300
2 | +++ /usr/local/directadmin/scripts/letsencrypt_poralix.sh 2017-04-11 16:28:31.278336745 +1200
3 | @@ -494,10 +494,26 @@
4 |
5 | send_signed_request "normal" "${CHALLENGE_URI}" "{\"resource\": \"challenge\", \"keyAuthorization\": \"${KEYAUTH}\"}"
6 |
7 | - if [ ${HTTP_STATUS} -ne 202 ] ; then
8 | - echo "Challenge error: ${RESPONSE}. Exiting..."
9 | - exit 1
10 | - fi
11 | + while [ ${HTTP_STATUS} -ne 202 ] ; do
12 | + echo "Challenge error: ${RESPONSE}."
13 | + echo "";
14 | + echo -n "Do you want to retry (yes/no): "
15 | + while read yesno;
16 | + do
17 | + case "${yesno}" in
18 | + yes|y)
19 | + send_signed_request "normal" "${CHALLENGE_URI}" "{\"resource\": \"challenge\", \"keyAuthorization\": \"${KEYAUTH}\"}"
20 | + break;
21 | + ;;
22 | + no|n)
23 | + exit 1;
24 | + ;;
25 | + *)
26 | + echo -n "Do you want to retry (yes/no): "
27 | + ;;
28 | + esac;
29 | + done;
30 | + done
31 |
32 | echo "Waiting for domain verification..."
33 | while [ "${CHALLENGE_STATUS}" = "pending" ]; do
34 | @@ -515,6 +531,13 @@
35 | echo "Challenge is ${CHALLENGE_STATUS}. Details: ${CHALLENGE_DETAIL}. Exiting..."
36 | exit 1
37 | fi
38 | +
39 | + echo -n "Sleep some ";
40 | + for n in `seq 1 5`; do
41 | + sleep 1;
42 | + echo -n '.';
43 | + done;
44 | + echo '';
45 | }
46 | done
47 |
48 |
--------------------------------------------------------------------------------
/letsencrypt/letsencrypt_poralix.patch:
--------------------------------------------------------------------------------
1 | letsencrypt_poralix-1.0.18.patch
--------------------------------------------------------------------------------
/letsencrypt/letsencrypt_poralix.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #VERSION=1.0.18
3 | # This script is written by Martynas Bendorius and DirectAdmin
4 | # It is used to create/renew let's encrypt certificate for a domain
5 | # Official DirectAdmin webpage: http://www.directadmin.com
6 | # Usage:
7 | # ./letsencrypt.sh
8 | MYUID=`/usr/bin/id -u`
9 | if [ "${MYUID}" != 0 ]; then
10 | echo "You require Root Access to run this script";
11 | exit 0;
12 | fi
13 |
14 | DEFAULT_KEY_SIZE=""
15 |
16 | if [ $# -lt 2 ]; then
17 | echo "Usage:";
18 | echo "$0 request|request_single|renew|revoke ()";
19 | echo "you gave #$#: $0 $1 $2 $3";
20 | echo "Multiple comma separated domains, owned by the same user, can be used for a certificate request"
21 | exit 0;
22 | elif [ $# -lt 3 ]; then
23 | #No key size specified, assign default one
24 | DEFAULT_KEY_SIZE=4096
25 | fi
26 | DA_BIN=/usr/local/directadmin/directadmin
27 | if [ ! -s ${DA_BIN} ]; then
28 | echo "Unable to find DirectAdmin binary /usr/local/directadmin/directadmin. Exiting..."
29 | exit 1
30 | fi
31 |
32 | #Staging/development
33 | #API_URI="acme-staging.api.letsencrypt.org"
34 | API_URI="acme-v01.api.letsencrypt.org"
35 | API="https://${API_URI}"
36 | LICENSE="https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
37 | LICENSE_NEW=$(curl -I -s https://acme-v01.api.letsencrypt.org/terms | (grep Location: || true) | awk -F ': ' '{print $2}' | tr -d '\n\r')
38 | if [ "$(echo "$LICENSE_NEW" | cut -c1-4)" == "http" ]; then
39 | LICENSE=$LICENSE_NEW
40 | fi
41 |
42 | CHALLENGETYPE="http-01"
43 | LICENSE_KEY_MIN_DATE=1470383674
44 |
45 | CURL=/usr/local/bin/curl
46 | if [ ! -x ${CURL} ]; then
47 | CURL=/usr/bin/curl
48 | fi
49 |
50 | CURL_OPTIONS="--connect-timeout 15 -k"
51 |
52 | OS=`uname`
53 |
54 | OPENSSL=/usr/bin/openssl
55 | TIMESTAMP=`date +%s`
56 |
57 | LETSENCRYPT_OPTION=`${DA_BIN} c | grep '^letsencrypt=' | cut -d= -f2`
58 | ACCESS_GROUP_OPTION=`${DA_BIN} c | grep '^secure_access_group=' | cut -d= -f2`
59 | FILE_CHOWN="diradmin:diradmin"
60 | FILE_CHMOD="640"
61 | if [ "${ACCESS_GROUP_OPTION}" != "" ]; then
62 | FILE_CHOWN="diradmin:${ACCESS_GROUP_OPTION}"
63 | fi
64 |
65 | #Encode data using base64 with URL-safe chars
66 | base64_encode() {
67 | ${OPENSSL} base64 -e | tr -d '\n\r' | tr "+/" "-_" | tr -d '= '
68 | }
69 |
70 | TASKQ=/usr/local/directadmin/data/task.queue
71 |
72 | #Send signed request
73 | send_signed_request() {
74 | REQ_TYPE="${1}"
75 | URL="${2}"
76 | PAYLOAD="${3}"
77 |
78 | #Use base64 for the payload
79 | PAYLOAD64="`echo -n \"${PAYLOAD}\" | base64_encode`"
80 |
81 | #Get nonce from acme-server
82 | FULL_NONCE="`${CURL} ${CURL_OPTIONS} --silent -I ${API}/directory`"
83 | NONCE="`echo \"${FULL_NONCE}\" | grep '^Replay-Nonce:' | cut -d' ' -f2 | tr -d '\n\r'`"
84 | if [ "${NONCE}" = "" ]; then
85 | echo "Nonce is empty. Exiting. dig output of ${API_URI}: "
86 | dig ${API_URI} +short
87 | echo "Full nonce request output:"
88 | echo "${FULL_NONCE}"
89 | exit 1
90 | fi
91 |
92 | #Create header without nonce, use thumbprint
93 | HEADER="{\"alg\": \"RS256\", \"jwk\": ${FOR_THUMBPRINT}}"
94 |
95 | #Create header with nonce encode as base64
96 | PROTECTED="{\"nonce\": \"${NONCE}\", \"alg\": \"RS256\", \"jwk\": ${FOR_THUMBPRINT}}"
97 |
98 | PROTECTED64="`echo -n ${PROTECTED} | base64_encode`"
99 |
100 | SIGN64="`echo -n \"${PROTECTED64}.${PAYLOAD64}\" | ${OPENSSL} dgst -sha256 -sign \"${LETSENCRYPT_ACCOUNT_KEY}\" | base64_encode`"
101 |
102 | #Form the BODY to send
103 | BODY="{\"header\": ${HEADER}, \"protected\": \"${PROTECTED64}\", \"payload\": \"${PAYLOAD64}\", \"signature\": \"${SIGN64}\"}"
104 |
105 | #Send the BODY, save the response
106 | if [ "${REQ_TYPE}" = "cert" ]; then
107 | CERT64="`${CURL} ${CURL_OPTIONS} --silent -X POST --data \"${BODY}\" \"${URL}\" | ${OPENSSL} base64 -e`"
108 | else
109 | RESPONSE="`${CURL} ${CURL_OPTIONS} -i --silent -X POST --data \"${BODY}\" \"${URL}\"`"
110 |
111 | if [ "${RESPONSE}" = "" ]; then
112 | echo "Response is empty. Command:"
113 | echo "${CURL} ${CURL_OPTIONS} -i --silent -X POST --data \"${BODY}\" \"${URL}\""
114 | echo "Exiting..."
115 | exit 1
116 | fi
117 | #HTTP status code
118 | HTTP_STATUS=`echo "${RESPONSE}" | grep -v 'HTTP.*100 Continue' | grep -m1 'HTTP.*' | awk '{print $2}'`
119 | fi
120 | }
121 |
122 | #Check if private key matches certificate
123 |
124 | checkPrivPubMatch() {
125 | PRIV="${1}"
126 | PUB="${2}"
127 | if [ -f "${PRIV}" ] && [ -f "${PUB}" ]; then
128 | MD5SUMPRIVMOD=`openssl rsa -noout -modulus -in ${PRIV}| openssl md5`
129 | MD5SUMPUBMOD=`openssl x509 -noout -modulus -in ${PUB} | openssl md5`
130 | if [ "${MD5SUMPRIVMOD}" = "${MD5SUMPUBMOD}" ]; then
131 | echo 0
132 | else
133 | echo 1
134 | fi
135 | else
136 | echo 2
137 | fi
138 | }
139 |
140 | ACTION=$1
141 | IS_SINGLE=false
142 | if [ "$1" = "request_single" ]; then
143 | IS_SINGLE=true
144 | ACTION=request
145 | fi
146 |
147 | DOMAIN=$2
148 | if [ "${DEFAULT_KEY_SIZE}" = "" ]; then
149 | KEY_SIZE=$3
150 | else
151 | KEY_SIZE=${DEFAULT_KEY_SIZE}
152 | fi
153 | CSR_CF_FILE=$4
154 | DOCUMENT_ROOT=$5
155 | #We need the domain to match in /etc/virtual/domainowners, if we use grep -F, we cannot use any regex'es including ^
156 |
157 | DOMAINARR_IN_USE=false
158 | if echo "${DOMAIN}" | grep -m1 -q ","; then
159 | DOMAINARR_IN_USE=true
160 | fi
161 | DOMAINARR=`echo "${DOMAIN}" | perl -p0 -e "s/,/ /g"`
162 |
163 | FOUNDDOMAIN=0
164 | for TDOMAIN in ${DOMAINARR}
165 | do
166 | DOMAIN=${TDOMAIN}
167 |
168 | DOMAIN_ESCAPED="`echo ${DOMAIN} | perl -p0 -e 's#\.#\\\.#g'`"
169 |
170 | if grep -m1 -q "^${DOMAIN_ESCAPED}:" /etc/virtual/domainowners; then
171 | USER=`grep -m1 "^${DOMAIN_ESCAPED}:" /etc/virtual/domainowners | cut -d' ' -f2`
172 | HOSTNAME=0
173 | FOUNDDOMAIN=1
174 | break
175 | elif grep -m1 -q "^${DOMAIN_ESCAPED}$" /etc/virtual/domains; then
176 | USER="root"
177 | if ${DA_BIN} c | grep -m1 -q "^servername=${DOMAIN_ESCAPED}\$"; then
178 | echo "Setting up certificate for a hostname: ${DOMAIN}"
179 | HOSTNAME=1
180 | FOUNDDOMAIN=1
181 | break
182 | else
183 | echo "Domain exists in /etc/virtual/domains, but is not set as a hostname in DirectAdmin. Unable to find 'servername=${DOMAIN}' in the output of '/usr/local/directadmin/directadmin c'. Exiting..."
184 | #exit 1
185 | fi
186 | else
187 | echo "Domain does not exist on the system. Unable to find ${DOMAIN} in /etc/virtual/domainowners. Exiting..."
188 | #exit 1
189 | fi
190 | done
191 |
192 | if [ ${FOUNDDOMAIN} -eq 0 ]; then
193 | echo "no valid domain found - exiting"
194 | exit 1
195 | fi
196 |
197 | if [ ${KEY_SIZE} -ne 2048 ] && [ ${KEY_SIZE} -ne 4096 ]; then
198 | echo "Wrong key size. It must be 2048 or 4096. Exiting..."
199 | exit 1
200 | fi
201 |
202 | if [ "${CSR_CF_FILE}" != "" ] && [ ! -s ${CSR_CF_FILE} ]; then
203 | echo "CSR config file ${CSR_CF_FILE} passed but does not exist or is empty."
204 | ls -la ${CSR_CF_FILE}
205 | exit 1
206 | fi
207 |
208 | EMAIL="${USER}@${DOMAIN}"
209 |
210 | DA_USERDIR="/usr/local/directadmin/data/users/${USER}"
211 | DA_CONFDIR="/usr/local/directadmin/conf"
212 | HOSTNAME_DIR="/var/www/html"
213 |
214 | if [ ! -d "${DA_USERDIR}" ] && [ "${HOSTNAME}" -eq 0 ]; then
215 | echo "${DA_USERDIR} not found, exiting..."
216 | exit 1
217 | elif [ ! -d "${DA_CONFDIR}" ] && [ "${HOSTNAME}" -eq 1 ]; then
218 | echo "${DA_CONFDIR} not found, exiting..."
219 | exit 1
220 | fi
221 |
222 | if [ "${HOSTNAME}" -eq 0 ]; then
223 | LETSENCRYPT_ACCOUNT_KEY="${DA_USERDIR}/letsencrypt.key"
224 | KEY="${DA_USERDIR}/domains/${DOMAIN}.key"
225 | CERT="${DA_USERDIR}/domains/${DOMAIN}.cert"
226 | CACERT="${DA_USERDIR}/domains/${DOMAIN}.cacert"
227 | CSR="${DA_USERDIR}/domains/${DOMAIN}.csr"
228 | SAN_CONFIG="${DA_USERDIR}/domains/${DOMAIN}.san_config"
229 | if [ "${DOCUMENT_ROOT}" != "" ]; then
230 | DOMAIN_DIR="${DOCUMENT_ROOT}"
231 | elif ${DA_BIN} c | grep -m1 -q '^letsencrypt=2$'; then
232 | USER_HOMEDIR="`grep -m1 \"^${USER}:\" /etc/passwd | cut -d: -f6`"
233 | DOMAIN_DIR="${USER_HOMEDIR}/domains/${DOMAIN}/public_html"
234 | else
235 | DOMAIN_DIR="${HOSTNAME_DIR}"
236 | fi
237 | WELLKNOWN_PATH="${DOMAIN_DIR}/.well-known/acme-challenge"
238 | else
239 | LETSENCRYPT_ACCOUNT_KEY="${DA_CONFDIR}/letsencrypt.key"
240 | KEY=`${DA_BIN} c |grep ^cakey= | cut -d= -f2`
241 | CERT=`${DA_BIN} c |grep ^cacert= | cut -d= -f2`
242 | CACERT=`${DA_BIN} c |grep ^carootcert= | cut -d= -f2`
243 | if [ "${CACERT}" = "" ]; then
244 | CACERT="${DA_CONFDIR}/carootcert.pem"
245 | fi
246 | CSR="${DA_CONFDIR}/ca.csr"
247 | SAN_CONFIG="${DA_CONFDIR}/ca.san_config"
248 | DOMAIN_DIR="${HOSTNAME_DIR}"
249 | WELLKNOWN_PATH="${DOMAIN_DIR}/.well-known/acme-challenge"
250 | fi
251 |
252 | challenge_check() {
253 | if [ ! -d ${WELLKNOWN_PATH} ]; then
254 | mkdir -p ${WELLKNOWN_PATH}
255 | fi
256 | touch ${WELLKNOWN_PATH}/letsencrypt_${TIMESTAMP}
257 | chown webapps:webapps ${WELLKNOWN_PATH}/letsencrypt_${TIMESTAMP}
258 | #Checking if http://www.domain.com/.well-known/acme-challenge/letsencrypt_${TIMESTAMP} is available
259 | if ! ${CURL} ${CURL_OPTIONS} -I -L -X GET http://${1}/.well-known/acme-challenge/letsencrypt_${TIMESTAMP} 2>/dev/null | grep -m1 -q 'HTTP.*200'; then
260 | echo 1
261 | else
262 | echo 0
263 | fi
264 | rm -f ${WELLKNOWN_PATH}/letsencrypt_${TIMESTAMP}
265 | }
266 |
267 | if [ "${CSR_CF_FILE}" != "" ] && [ -s ${CSR_CF_FILE} ]; then
268 | if grep -q -m1 '^emailAddress' ${CSR_CF_FILE}; then
269 | EMAIL="`grep '^emailAddress' ${CSR_CF_FILE} | awk '{print $3}'`"
270 | fi
271 | elif [ "${CSR_CF_FILE}" = "" ] && [ -s ${SAN_CONFIG} ]; then
272 | if grep -q -m1 '^emailAddress' ${SAN_CONFIG}; then
273 | EMAIL="`grep '^emailAddress' ${SAN_CONFIG} | awk '{print $3}'`"
274 | fi
275 | fi
276 |
277 | #It could be a symlink, so we use -e
278 | if [ ! -e "${DOMAIN_DIR}" ]; then
279 | echo "${DOMAIN_DIR} does not exist. Exiting..."
280 | exit 1
281 | fi
282 |
283 | #ensure the letsencrypt.key is new enough
284 | if [ -s "${LETSENCRYPT_ACCOUNT_KEY}" ]; then
285 | if [ "${OS}" = "FreeBSD" ]; then
286 | STAT_CMD="/usr/bin/stat -f %m ${LETSENCRYPT_ACCOUNT_KEY}"
287 | else
288 | STAT_CMD="/usr/bin/stat --printf %Y ${LETSENCRYPT_ACCOUNT_KEY}"
289 | fi
290 |
291 | LAST_CHANGED=`${STAT_CMD} 2>/dev/null`
292 | if [ "${LAST_CHANGED}" = "" ]; then
293 | echo "Unable to get last modification time from key using:";
294 | echo "${STAT_CMD}";
295 | ${STAT_CMD}
296 | else
297 | #got a number, hopfully.
298 |
299 | if [ "${LAST_CHANGED}" -lt "${LICENSE_KEY_MIN_DATE}" ]; then
300 | echo "${LETSENCRYPT_ACCOUNT_KEY} was older than recent license agreement. Deleting it, and creating a new one";
301 | rm -f ${LETSENCRYPT_ACCOUNT_KEY}
302 | fi
303 | fi
304 | fi
305 |
306 | #Create account KEY if it does not exist
307 | OLD_KEY=1
308 | if [ ! -s "${LETSENCRYPT_ACCOUNT_KEY}" ]; then
309 | echo "Generating ${KEY_SIZE} bit RSA key for let's encrypt account..."
310 | echo "openssl genrsa ${KEY_SIZE} > \"${LETSENCRYPT_ACCOUNT_KEY}\""
311 | ${OPENSSL} genrsa ${KEY_SIZE} > "${LETSENCRYPT_ACCOUNT_KEY}"
312 | chown diradmin:diradmin ${LETSENCRYPT_ACCOUNT_KEY}
313 | chmod 600 ${LETSENCRYPT_ACCOUNT_KEY}
314 | OLD_KEY=0
315 | fi
316 |
317 | #We use perl here to convert HEX to BIN
318 | PUBLIC_EXPONENT64=`${OPENSSL} rsa -in "${LETSENCRYPT_ACCOUNT_KEY}" -noout -text | grep "^publicExponent:" | awk '{print $3}' | cut -d'(' -f2 | cut -d')' -f1 | tr -d '\r\n' | tr -d 'x' | perl -n0 -e 's/([0-9a-f]{2})/print chr hex $1/gie' | base64_encode`
319 | PUBLIC_MODULUS64=`${OPENSSL} rsa -in "${LETSENCRYPT_ACCOUNT_KEY}" -noout -modulus | cut -d'=' -f2 | perl -n0 -e 's/([0-9a-f]{2})/print chr hex $1/gie' | base64_encode`
320 |
321 | FOR_THUMBPRINT="{\"e\": \"${PUBLIC_EXPONENT64}\", \"kty\": \"RSA\", \"n\": \"${PUBLIC_MODULUS64}\"}"
322 | HAS_SHA_256=`${OPENSSL} help 2>&1 | grep -c sha256`
323 | if [ "${HAS_SHA_256}" -gt 0 ]; then
324 | THUMBPRINT=`echo -n "${FOR_THUMBPRINT}" | tr -d ' ' | ${OPENSSL} sha256 -binary | base64_encode`
325 | else
326 | THUMBPRINT=`echo -n "${FOR_THUMBPRINT}" | tr -d ' ' | ${OPENSSL} sha -sha256 -binary | base64_encode`
327 | fi
328 |
329 | #Register the new key with the acme-server
330 | if [ ${OLD_KEY} -eq 0 ]; then
331 | send_signed_request "normal" "${API}/acme/new-reg" '{"resource": "new-reg", "contact":["'"mailto:${EMAIL}"'"], "agreement": "'"${LICENSE}"'"}'
332 | if [ "${HTTP_STATUS}" = "" ] || [ "${HTTP_STATUS}" -eq 201 ] ; then
333 | echo "Account has been registered."
334 | elif [ "${HTTP_STATUS}" -eq 409 ] ; then
335 | echo "Account is already registered."
336 | else
337 | echo "Account registration error. Response: ${RESPONSE}."
338 | exit 1
339 | fi
340 | fi
341 |
342 | if [ "${ACTION}" = "revoke" ]; then
343 | if [ ! -e ${CERT} ]; then
344 | echo "Certificate ${CERT} does not exist, there is nothing to revoke."
345 | exit 1
346 | fi
347 | DER64="`${OPENSSL} x509 -in ${CERT} -inform PEM -outform DER | base64_encode`"
348 | send_signed_request "normal" "${API}/acme/revoke-cert" '{"resource": "revoke-cert", "certificate": "'"${DER64}"'"}'
349 | if [ "${HTTP_STATUS}" = "" ] || [ "${HTTP_STATUS}" -eq 200 ] ; then
350 | echo "Certificate has been successfully revoked."
351 | else
352 | echo "Certificate revocation error. Response: ${RESPONSE}."
353 | exit 1
354 | fi
355 | exit 0
356 | fi
357 |
358 | #Overwrite san_config file if csr_cf_file path is different
359 | if [ "${CSR_CF_FILE}" != "" ] && [ "${CSR_CF_FILE}" != "${SAN_CONFIG}" ]; then
360 | cp -f ${CSR_CF_FILE} ${SAN_CONFIG}
361 | fi
362 |
363 | #For multi-domains (www and non-www one)
364 | SAN=""
365 |
366 | if [ -s ${SAN_CONFIG} ] && ! ${DOMAINARR_IN_USE} && ! ${IS_SINGLE}; then
367 | SAN="`cat \"${SAN_CONFIG}\" | grep '^subjectAltName=' | cut -d= -f2`"
368 | elif [ "${HOSTNAME}" -eq 0 ]; then
369 | if ${DOMAINARR_IN_USE} || ${IS_SINGLE}; then
370 | SAN=""
371 | for TDOMAIN in ${DOMAINARR}
372 | do
373 | CHALLENGE_TEST=`challenge_check ${TDOMAIN}`
374 | if [ ${CHALLENGE_TEST} -ne 1 ]; then
375 | SAN="${SAN}, DNS:${TDOMAIN}"
376 | else
377 | echo "skipping ${TDOMAIN} challenge test failed"
378 | fi
379 | done
380 | SAN=`echo ${SAN} | grep -o -E "DNS:(.*)"`
381 | elif ! echo "${DOMAIN}" | grep -q "^www\."; then
382 | #We have a domain without www., add www domain to to SAN too
383 | SAN="DNS:${DOMAIN}, DNS:www.${DOMAIN}"
384 | else
385 | #We have a domain with www., drop www and add it to SAN too
386 | DOMAIN2=`echo ${DOMAIN} | perl -p0 -e 's#^www.##'`
387 | SAN="DNS:${DOMAIN2}, DNS:www.${DOMAIN2}"
388 | fi
389 | else
390 | #For hostname, we add www, mail, ftp, pop, smtp to the SAN
391 | if ${DOMAINARR_IN_USE} || ${IS_SINGLE}; then
392 | SAN=""
393 | for TDOMAIN in ${DOMAINARR}
394 | do
395 | SAN="${SAN}, DNS:${TDOMAIN}"
396 | done
397 | SAN=`echo ${SAN} | egrep -o "DNS:(.*)"`
398 | else
399 |
400 | if ! echo "${DOMAIN}" | grep -q "^www\."; then
401 | #We have a domain without www., add www domain to to SAN too
402 | MAIN_HOST=${DOMAIN}
403 | else
404 | #We have a domain with www., drop www and add it to SAN too
405 | DOMAIN2=`echo ${DOMAIN} | perl -p0 -e 's#^www.##'`
406 | MAIN_HOST=${DOMAIN2}
407 | fi
408 | SAN="DNS:${MAIN_HOST}"
409 | for A in www mail ftp pop smtp; do
410 | {
411 | H=${A}.${MAIN_HOST}
412 | CHALLENGE_TEST=`challenge_check ${H}`
413 | if [ ${CHALLENGE_TEST} -eq 1 ]; then
414 | echo "${H} was skipped due to unreachable http://${H}/.well-known/acme-challenge/letsencrypt_${TIMESTAMP} file. Not adding to san_config";
415 | else
416 | SAN="${SAN}, DNS:${H}"
417 | fi
418 | };
419 | done;
420 | fi
421 | fi
422 |
423 | DOMAINS="`echo ${SAN} | tr -d '\",' | perl -p0 -e 's#DNS:##g'`"
424 | CN_DOMAIN=${DOMAIN}
425 | if ! echo "${DOMAINS}" | grep -m1 -q "DNS:${DOMAIN},"; then
426 | CN_DOMAIN="`echo ${SAN} | cut -d':' -f2 | cut -d',' -f1`"
427 | fi
428 | if [ "${CN_DOMAIN}" = "" ]; then
429 | CN_DOMAIN=${DOMAIN}
430 | fi
431 |
432 | #Create san_config
433 | if [ ! -s ${SAN_CONFIG} ] || ${DOMAINARR_IN_USE} || ${IS_SINGLE}; then
434 | echo "[ req_distinguished_name ]" > ${SAN_CONFIG}
435 | echo "CN = ${CN_DOMAIN}" >> ${SAN_CONFIG}
436 | echo "[ req ]" >> ${SAN_CONFIG}
437 | echo "distinguished_name = req_distinguished_name" >> ${SAN_CONFIG}
438 | echo "[SAN]" >> ${SAN_CONFIG}
439 | echo "subjectAltName=${SAN}" >> ${SAN_CONFIG}
440 | fi
441 |
442 | chown diradmin:diradmin ${SAN_CONFIG}
443 | chmod 600 ${SAN_CONFIG}
444 |
445 | #For each of the domains, we need to verify them
446 | for single_domain in ${DOMAINS}; do {
447 | # Connect to the acme-server to get a new challenge token to verify the domain
448 | echo "Getting challenge for ${single_domain} from acme-server..."
449 | send_signed_request "normal" "${API}/acme/new-authz" '{"resource": "new-authz", "identifier": {"type": "dns", "value": "'"${single_domain}"'"}}'
450 |
451 | # poralix
452 | if [ "${HTTP_STATUS}" -ne 201 ] ; then
453 | sleep 1;
454 | ERROR500=$(echo ${RESPONSE} | grep -c 'HTTP/1.1 500 Internal Server Error');
455 | if [ "${ERROR500}" -ne 0 ]; then
456 | echo "Error 500 occured in authz request: ${RESPONSE}. Trying once again...";
457 | send_signed_request "normal" "${API}/acme/new-authz" '{"resource": "new-authz", "identifier": {"type": "dns", "value": "'"${single_domain}"'"}}';
458 | fi;
459 | fi;
460 |
461 | #Account has a key for let's encrypt, but it's not registered
462 | if [ "${HTTP_STATUS}" -eq 403 ] ; then
463 | echo "User let's encrypt key has been found, but not registered. Registering..."
464 | send_signed_request "normal" "${API}/acme/new-reg" '{"resource": "new-reg", "contact":["'"mailto:${EMAIL}"'"], "agreement": "'"${LICENSE}"'"}'
465 | if [ "${HTTP_STATUS}" = "" ] || [ "${HTTP_STATUS}" -eq 201 ] ; then
466 | echo "Account has been registered."
467 | elif [ "${HTTP_STATUS}" -eq 409 ] ; then
468 | echo "Account is already registered."
469 | else
470 | echo "Account registration error. Response: ${RESPONSE}."
471 | exit 1
472 | fi
473 |
474 | echo "Getting challenge for ${DOMAIN} from acme-server..."
475 | send_signed_request "normal" "${API}/acme/new-authz" '{"resource": "new-authz", "identifier": {"type": "dns", "value": "'"${single_domain}"'"}}'
476 | fi
477 |
478 | if [ "${HTTP_STATUS}" -ne 201 ] ; then
479 | echo "new-authz error: ${RESPONSE}. Exiting..."
480 | exit 1
481 | fi
482 |
483 | CHALLENGE="`echo "${RESPONSE}" | awk '/\"type\": \"http-01\"/,/}/'`"
484 |
485 | CHALLENGE_TOKEN="`echo \"${CHALLENGE}\" | tr ',' '\n' | grep -m1 '\"token\":' | cut -d'\"' -f4`"
486 | CHALLENGE_URI="`echo \"${CHALLENGE}\" | tr ',' '\n' | grep -m1 '\"uri\":' | cut -d'\"' -f4`"
487 | CHALLENGE_STATUS="`echo \"${CHALLENGE}\" | tr ',' '\n' | grep -m1 '\"status\":' | cut -d'\"' -f4`"
488 |
489 | KEYAUTH="${CHALLENGE_TOKEN}.${THUMBPRINT}"
490 |
491 | if [ "${DOMAIN_DIR}" = "/var/www/html" ]; then
492 | mkdir -p ${WELLKNOWN_PATH}
493 | chown webapps:webapps ${HOSTNAME_DIR}/.well-known
494 | chown webapps:webapps ${WELLKNOWN_PATH}
495 | fi
496 |
497 | if [ ! -d "${WELLKNOWN_PATH}" ]; then
498 | echo "Cannot find ${WELLKNOWN_PATH}. Create this path, ensure it's chowned to the User.";
499 | exit 1;
500 | fi
501 |
502 | echo "${KEYAUTH}" > "${WELLKNOWN_PATH}/${CHALLENGE_TOKEN}"
503 |
504 | chown webapps:webapps "${WELLKNOWN_PATH}/${CHALLENGE_TOKEN}"
505 |
506 | #Checking if challenge will be reachable
507 | CHALLENGE_TEST=`challenge_check ${single_domain}`
508 | if [ ${CHALLENGE_TEST} -eq 1 ]; then
509 | echo "Error: http://${single_domain}/.well-known/acme-challenge/letsencrypt_${TIMESTAMP} is not reachable. Aborting the script."
510 | echo "dig output for ${single_domain}:"
511 | dig ${single_domain} +short
512 | if [ ${LETSENCRYPT_OPTION} -eq 1 ]; then
513 | echo "Please make sure /.well-known alias is setup in WWW server."
514 | else
515 | echo "Please make sure .htaccess or WWW server is not preventing access to /.well-known folder."
516 | fi
517 | exit 1
518 | fi
519 |
520 | send_signed_request "normal" "${CHALLENGE_URI}" "{\"resource\": \"challenge\", \"keyAuthorization\": \"${KEYAUTH}\"}"
521 |
522 | if [ ${HTTP_STATUS} -ne 202 ] ; then
523 | echo -n "Challenge error: ${RESPONSE}. Trying again..."
524 | for n in `seq 1 5`; do
525 | sleep 1;
526 | echo -n '.';
527 | done;
528 | echo "";
529 | send_signed_request "normal" "${CHALLENGE_URI}" "{\"resource\": \"challenge\", \"keyAuthorization\": \"${KEYAUTH}\"}"
530 | fi
531 |
532 | if [ ${HTTP_STATUS} -ne 202 ] ; then
533 | echo "Challenge error: ${RESPONSE}. Exiting..."
534 | exit 1
535 | fi
536 |
537 | echo "Waiting for domain verification..."
538 | while [ "${CHALLENGE_STATUS}" = "pending" ]; do
539 | sleep 1
540 | FULL_CHALLENGE_STATUS="`${CURL} ${CURL_OPTIONS} --silent -X GET \"${CHALLENGE_URI}\"`"
541 | CHALLENGE_STATUS="`echo ${FULL_CHALLENGE_STATUS} | tr ',' '\n' | grep -m1 '\"status\":' | cut -d'\"' -f4`"
542 | CHALLENGE_DETAIL="`echo ${FULL_CHALLENGE_STATUS} | tr ',' '\n' | grep -m1 '\"detail\":' | cut -d'\"' -f4`"
543 | done
544 |
545 | rm -f "${WELLKNOWN_PATH}/${CHALLENGE_TOKEN}"
546 |
547 | if [ "${CHALLENGE_STATUS}" = "valid" ]; then
548 | echo "Challenge is valid."
549 | else
550 | echo "Challenge is ${CHALLENGE_STATUS}. Details: ${CHALLENGE_DETAIL}. Exiting..."
551 | exit 1
552 | fi
553 |
554 | # poralix
555 | echo -n "Sleep some ";
556 | for n in `seq 1 5`; do
557 | sleep 1;
558 | echo -n '.';
559 | done;
560 | echo '';
561 | }
562 | done
563 |
564 | #Create domain key, also generate CSR for the domain
565 | echo "Generating ${KEY_SIZE} bit RSA key for ${DOMAIN}..."
566 | echo "openssl genrsa ${KEY_SIZE} > \"${KEY}.new\""
567 | ${OPENSSL} genrsa ${KEY_SIZE} > "${KEY}.new"
568 |
569 | ${OPENSSL} req -new -sha256 -key "${KEY}.new" -subj "/CN=${CN_DOMAIN}" -reqexts SAN -config "${SAN_CONFIG}" -out "${CSR}"
570 |
571 | #Request certificate from let's encrypt
572 | DER64="`${OPENSSL} req -in ${CSR} -outform DER | base64_encode`"
573 |
574 | send_signed_request "cert" "${API}/acme/new-cert" "{\"resource\": \"new-cert\", \"csr\": \"${DER64}\"}"
575 |
576 | SIZE_OF_CERT64="`echo ${CERT64} | wc -c`"
577 | #It's likely text encoded if there are less than 500 chars, so we have a JSON response
578 | if [ ${SIZE_OF_CERT64} -lt 500 ]; then
579 | echo "Size of certificate response is smaller than 500 characters, it means something went wrong. Printing response..."
580 | echo "${CERT64}" | ${OPENSSL} enc -base64 -d | grep -o '"detail": "[^,]*"'
581 | echo ""
582 | exit 1
583 | fi
584 |
585 | echo "-----BEGIN CERTIFICATE-----" > ${CERT}.new
586 | echo "${CERT64}" >> ${CERT}.new
587 | echo "-----END CERTIFICATE-----" >> ${CERT}.new
588 |
589 | ${OPENSSL} x509 -text < ${CERT}.new > /dev/null
590 | if [ $? -ne 0 ]; then
591 | echo "Certificate error in ${CERT}. Exiting..."
592 | /bin/rm -f ${KEY}.new ${CERT}.new
593 | exit 1
594 | fi
595 |
596 | getCacert() {
597 | CACERT64=`${CURL} -k --silent -X GET "${API}/acme/issuer-cert" | ${OPENSSL} base64 -e`
598 | SIZE_OF_CACERT64="`echo ${CERT64} | wc -c`"
599 | if [ ${SIZE_OF_CACERT64} -gt 500 ]; then
600 | echo "-----BEGIN CERTIFICATE-----" > ${CACERT}.new
601 | echo "${CACERT64}" >> ${CACERT}.new
602 | echo "-----END CERTIFICATE-----" >> ${CACERT}.new
603 | fi
604 | }
605 |
606 | getCacert
607 | CACERT_LINES=`cat ${CACERT}.new | wc -l`
608 | if [ ${CACERT_LINES} -lt 4 ]; then
609 | echo "Unable to retrieve CA root cert. Retrying..."
610 | getCacert
611 | fi
612 |
613 | CACERT_LINES=`cat ${CACERT}.new | wc -l`
614 | if [ ${CACERT_LINES} -lt 4 ]; then
615 | echo "Retry for CA root cert failed."
616 | if [ -s ${CACERT} ]; then
617 | echo "Using old CA root certificate ${CACERT}."
618 | rm -f ${CACERT}.new
619 | else
620 | echo "Exiting.."
621 | exit 1
622 | fi
623 | fi
624 |
625 | echo -n "Checking Certificate Private key match... "
626 | CHECKPRIVPUBRES=`checkPrivPubMatch ${KEY}.new ${CERT}.new`
627 | if [ $CHECKPRIVPUBRES -ne 1 ]; then
628 | echo "Match!"
629 | else
630 | echo "!!!Certificate mismatch"
631 | exit 1
632 | fi
633 |
634 | #everything went well, move the new files.
635 | /bin/mv -f ${KEY}.new ${KEY}
636 | /bin/mv -f ${CERT}.new ${CERT}
637 | if [ -s ${CACERT}.new ]; then
638 | /bin/mv -f ${CACERT}.new ${CACERT}
639 | fi
640 | if [ ! -s ${CACERT} ]; then
641 | echo "-----BEGIN CERTIFICATE-----
642 | MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
643 | MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
644 | DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
645 | SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
646 | GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
647 | AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
648 | q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
649 | SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
650 | Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
651 | a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
652 | /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
653 | AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
654 | CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
655 | bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
656 | c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
657 | VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
658 | ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
659 | MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
660 | Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
661 | AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
662 | uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
663 | wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
664 | X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
665 | PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
666 | KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
667 | -----END CERTIFICATE-----" > ${CACERT}
668 | fi
669 | date +%s > ${CERT}.creation_time
670 |
671 | cat ${CERT} ${CACERT} > ${CERT}.combined
672 |
673 | chown ${FILE_CHOWN} ${KEY} ${CERT} ${CERT}.combined ${CACERT} ${CSR} ${CERT}.creation_time
674 | chmod ${FILE_CHMOD} ${KEY} ${CERT} ${CERT}.combined ${CACERT} ${CSR} ${CERT}.creation_time
675 |
676 | #Change exim, apache/nginx certs
677 | if [ "${HOSTNAME}" -eq 1 ]; then
678 | echo "DirectAdmin certificate has been setup."
679 |
680 | #Exim
681 | echo "Setting up cert for Exim..."
682 | EXIMKEY="/etc/exim.key"
683 | EXIMCERT="/etc/exim.cert"
684 | cp -f ${KEY} ${EXIMKEY}
685 | cat ${CERT} ${CACERT} > ${EXIMCERT}
686 | chown mail:mail ${EXIMKEY} ${EXIMCERT}
687 | chmod 600 ${EXIMKEY} ${EXIMCERT}
688 |
689 | echo "action=exim&value=restart" >> ${TASKQ}
690 | echo "action=dovecot&value=restart" >> ${TASKQ}
691 |
692 | #Apache
693 | echo "Setting up cert for WWW server..."
694 | if [ -d /etc/httpd/conf/ssl.key ] && [ -d /etc/httpd/conf/ssl.crt ]; then
695 | APACHEKEY="/etc/httpd/conf/ssl.key/server.key"
696 | APACHECERT="/etc/httpd/conf/ssl.crt/server.crt"
697 | APACHECACERT="/etc/httpd/conf/ssl.crt/server.ca"
698 | APACHECERTCOMBINED="${APACHECERT}.combined"
699 | cp -f ${KEY} ${APACHEKEY}
700 | cp -f ${CERT} ${APACHECERT}
701 | cp -f ${CACERT} ${APACHECACERT}
702 | cat ${APACHECERT} ${APACHECACERT} > ${APACHECERTCOMBINED}
703 | chown root:root ${APACHEKEY} ${APACHECERT} ${APACHECACERT} ${APACHECERTCOMBINED}
704 | chmod 600 ${APACHEKEY} ${APACHECERT} ${APACHECACERT} ${APACHECERTCOMBINED}
705 |
706 | echo "action=httpd&value=restart" >> ${TASKQ}
707 | fi
708 |
709 | #Nginx
710 | if [ -d /etc/nginx/ssl.key ] && [ -d /etc/nginx/ssl.crt ]; then
711 | NGINXKEY="/etc/nginx/ssl.key/server.key"
712 | NGINXCERT="/etc/nginx/ssl.crt/server.crt"
713 | NGINXCACERT="/etc/nginx/ssl.crt/server.ca"
714 | NGINXCERTCOMBINED="${NGINXCERT}.combined"
715 | cp -f ${KEY} ${NGINXKEY}
716 | cp -f ${CERT} ${NGINXCERT}
717 | cp -f ${CACERT} ${NGINXCACERT}
718 | cat ${NGINXCERT} ${NGINXCACERT} > ${NGINXCERTCOMBINED}
719 | chown root:root ${NGINXKEY} ${NGINXCERT} ${NGINXCACERT} ${NGINXCERTCOMBINED}
720 | chmod 600 ${NGINXKEY} ${NGINXCERT} ${NGINXCACERT} ${NGINXCERTCOMBINED}
721 |
722 | echo "action=nginx&value=restart" >> ${TASKQ}
723 | fi
724 |
725 | #FTP
726 | echo "Setting up cert for FTP server..."
727 | cat ${KEY} ${CERT} ${CACERT} > /etc/pure-ftpd.pem
728 | chmod 600 /etc/pure-ftpd.pem
729 | chown root:root /etc/pure-ftpd.pem
730 |
731 | if /usr/local/directadmin/directadmin c | grep -m1 -q "^pureftp=1\$"; then
732 | echo "action=pure-ftpd&value=restart" >> ${TASKQ}
733 | else
734 | echo "action=proftpd&value=restart" >> ${TASKQ}
735 | fi
736 |
737 | echo "action=directadmin&value=restart" >> ${TASKQ}
738 |
739 | echo "The services will be restarted in about 1 minute via the dataskq."
740 | fi
741 |
742 | echo "Certificate for ${DOMAIN} has been created successfully!"
743 | exit 0
744 |
--------------------------------------------------------------------------------
/letsencrypt/poralix_patch_chain.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #----------------------------------------------------------------------
3 | # Description: A script to force Let's Encrypt to use DST Root CA X3
4 | #----------------------------------------------------------------------
5 | # Author: Alex Grebenschikov, www.poralix.com
6 | # Created at: Fri Dec 16 17:45:36 +07 2022
7 | # Last modified: Fri Dec 16 17:45:36 +07 2022
8 | # Version: 0.1 $ Fri Dec 16 17:45:36 +07 2022
9 | #----------------------------------------------------------------------
10 | # Copyright (c) 2022 Alex Grebenschikov, www.poralix.com
11 |
12 | # INSTALLATION:
13 | # =====================================================================
14 | # RUN AS ROOT:
15 | # =====================================================================
16 | # mkdir -p /usr/local/directadmin/custombuild/custom/hooks/letsencrypt/post/
17 | # cd /usr/local/directadmin/custombuild/custom/hooks/letsencrypt/post/
18 | #
19 | # COPY/MOVE FILE TO THE CREATED FOLDER AND RUN:
20 | #
21 | # wget -O poralix_patch_chain.sh https://raw.githubusercontent.com/poralix/directadmin-utils/master/letsencrypt/poralix_patch_chain.sh
22 | # chmod 750 poralix_patch_chain.sh
23 | # /usr/local/directadmin/custombuild/build letsencrypt
24 | #
25 |
26 | echo "";
27 | echo "Running patch script from Poralix:";
28 | echo "";
29 |
30 | set -x;
31 | \cp -fp /usr/local/directadmin/scripts/letsencrypt.sh{,~orig};
32 | perl -pi -e "s/ISRG Root X1/DST Root CA X3/" /usr/local/directadmin/scripts/letsencrypt.sh;
33 |
--------------------------------------------------------------------------------
/misc/README.md:
--------------------------------------------------------------------------------
1 | # A script to manage private_html directories on Directadmin servers #
2 |
3 | - private_html_symlink.sh
4 |
5 | ```
6 | Usage ./private_html_symlink.sh
7 | --list=all - list private_html status for all domains
8 | --list=dirs - list only domains with static folder for private_html
9 | --list=links - list only domains with symlink for private_html
10 | --list=no - list only domains without private_html at all
11 |
12 | --create-symlink=dirs - Replace directory private_html with a symlink
13 | --create-symlink=no - Create symlink private_html where it does not exist
14 | ```
15 |
16 | # A script to list DirectAdmin domains
17 |
18 | - da_domains.sh
19 |
20 | ```
21 | Description:
22 | This is a script to list directadmin domains with a requested from
23 | DNS additional information.
24 |
25 | Usage:
26 | ./da_domains.sh
27 |
28 | Options:
29 | --domains - just list domains without DNS queries
30 | --ns - list domains with their nameservers
31 | --mx - list domains with their MX records
32 | --ip4 - list domains with their IPv4
33 | --ip6 - list domains with their IPv6
34 | ```
35 |
36 |
--------------------------------------------------------------------------------
/misc/da_domains.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #----------------------------------------------------------------------
3 | # Description: A script for listing all domains from DirectAdmin
4 | #----------------------------------------------------------------------
5 | # Author: Alex Grebenschikov, www.poralix.com
6 | # Created at: Mon Oct 31 13:21:06 +07 2022
7 | # Last modified: Fri Dec 16 17:27:30 +07 2022
8 | # Version: 0.2.1 $ Mon Nov 21 11:44:46 +07 2022
9 | #----------------------------------------------------------------------
10 | # Copyright (c) 2022 Alex Grebenschikov, www.poralix.com
11 | #----------------------------------------------------------------------
12 |
13 | DNS_RESOLVER="1.1.1.1";
14 |
15 | die()
16 | {
17 | echo $1;
18 | exit $2;
19 | }
20 |
21 | usage()
22 | {
23 | echo "#----------------------------------------------------------------------
24 | # Copyright (c) 2022 Alex Grebenschikov, www.poralix.com
25 | #----------------------------------------------------------------------
26 |
27 | Description:
28 | This is a script to list directadmin domains with a requested from
29 | DNS additional information.
30 |
31 | Usage:
32 | $0
33 |
34 | Options:
35 | --domains - just list domains without DNS queries
36 | --ns - list domains with their nameservers
37 | --mx - list domains with their MX records
38 | --ip4 - list domains with their IPv4
39 | --ip6 - list domains with their IPv6
40 | ";
41 | exit 0;
42 | }
43 |
44 | domains()
45 | {
46 | for DOM in $(awk -F: {'print $1'} /etc/virtual/domainowners | sort | uniq); do echo - $DOM; done
47 | }
48 |
49 | nameservers()
50 | {
51 | for DOM in $(awk -F: {'print $1'} /etc/virtual/domainowners | sort | uniq); do echo - $DOM: $(dig +short NS "@${DNS_RESOLVER}" "${DOM}" | sort | xargs); done
52 | }
53 |
54 | ip4()
55 | {
56 | for DOM in $(awk -F: {'print $1'} /etc/virtual/domainowners | sort | uniq); do echo - $DOM: $(dig +short A "@${DNS_RESOLVER}" "${DOM}" | sort | xargs); done
57 | }
58 |
59 | ip6()
60 | {
61 | for DOM in $(awk -F: {'print $1'} /etc/virtual/domainowners | sort | uniq); do echo - $DOM: $(dig +short AAAA "@${DNS_RESOLVER}" "${DOM}" | sort | xargs); done
62 | }
63 |
64 | mx()
65 | {
66 | for DOM in $(awk -F: {'print $1'} /etc/virtual/domainowners | sort | uniq); do echo - $DOM: $(dig +short MX "@${DNS_RESOLVER}" "${DOM}" | sort | xargs); done
67 | }
68 |
69 | run_cmd()
70 | {
71 | case $1 in
72 | domains)
73 | domains;
74 | ;;
75 | nameservers)
76 | nameservers;
77 | ;;
78 | ip4)
79 | ip4;
80 | ;;
81 | ip6)
82 | ip6;
83 | ;;
84 | mx)
85 | mx;
86 | ;;
87 | usage|*)
88 | usage;
89 | ;;
90 | esac;
91 | }
92 |
93 | test -e "/etc/virtual/domainowners" || die "Error: Not a directadmin server?" 1;
94 |
95 | RUN="";
96 |
97 | for CMD in $@
98 | do
99 | case $CMD in
100 | --only-domains|--domains)
101 | RUN="domains";
102 | ;;
103 | --ns)
104 | RUN="nameservers";
105 | ;;
106 | --ip4)
107 | RUN="ip4";
108 | ;;
109 | --ip6)
110 | RUN="ip6";
111 | ;;
112 | --mx)
113 | RUN="mx";
114 | ;;
115 | --help)
116 | RUN="usage";
117 | ;;
118 | esac;
119 | done;
120 |
121 | run_cmd "${RUN}";
122 |
123 | exit 0;
124 |
--------------------------------------------------------------------------------
/misc/private_html_symlink.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #######################################################################################
3 | # #
4 | # A script to manage private_html directories on Directadmin servers #
5 | # #
6 | #######################################################################################
7 | # #
8 | # Version: 0.1 (Thu Aug 31 18:12:01 +07 2017) #
9 | # Written by: Alex S Grebenschikov (zEitEr) #
10 | # Site: www.poralix.com E-mail: support@poralix.com #
11 | # #
12 | #######################################################################################
13 | #######################################################################################
14 | ## #
15 | ## MIT License #
16 | ## #
17 | ## Copyright (c) 2016 Alex S Grebenschikov (www.poralix.com) #
18 | ## #
19 | ## Permission is hereby granted, free of charge, to any person obtaining a copy #
20 | ## of this software and associated documentation files (the "Software"), to deal #
21 | ## in the Software without restriction, including without limitation the rights #
22 | ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell #
23 | ## copies of the Software, and to permit persons to whom the Software is #
24 | ## furnished to do so, subject to the following conditions: #
25 | ## #
26 | ## The above copyright notice and this permission notice shall be included in all #
27 | ## copies or substantial portions of the Software. #
28 | ## #
29 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
30 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
31 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
32 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
33 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #
34 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #
35 | ## SOFTWARE. #
36 | ## #
37 | #######################################################################################
38 |
39 | function usage()
40 | {
41 | echo "
42 | ######################################################################################
43 | # A script to manage private_html directories on Directadmin servers #
44 | # Written by: Alex S Grebenschikov (zEitEr) #
45 | ######################################################################################
46 |
47 | Usage $0
48 | --list - list private_html status for all domains
49 | --list-dirs - list only domains with static folder for private_html
50 | --list-links - list only domains with symlink for private_html
51 | --list-no - list only domains without private_html at all
52 |
53 | --create-symlink=dirs - Replace directory private_html with a symlink
54 | --create-symlink=no - Create symlink private_html where it does not exist
55 | ";
56 | }
57 |
58 | function doList()
59 | {
60 | for DH in `ls -d1 /home/*/domains/*/ 2>/dev/null | egrep -v "/shared/|/suspended/|/default/|/sharedip/" | sort`;
61 | do
62 | DOMAIN=$(echo ${DH} | cut -d\/ -f5);
63 | if [ -L "${DH}/private_html" ]; then
64 | [ "${1}" == "links" ] && echo "[S] Domain ${DOMAIN} has private_html symlink in ${DH}";
65 | elif [ -d "${DH}/private_html" ]; then
66 | [ "${1}" == "dirs" ] && echo "[D] Domain ${DOMAIN} has private_html folder in ${DH}";
67 | else
68 | [ "${1}" == "no" ] && echo "[-] Domain ${DOMAIN} has no private_html folder in ${DH}";
69 | fi;
70 | done;
71 | }
72 |
73 | function doCreateSymlink()
74 | {
75 | for DH in `ls -d1 /home/*/domains/*/ 2>/dev/null | egrep -v "/shared/|/suspended/|/default/|/sharedip/" | sort`;
76 | do
77 | USER=$(echo ${DH} | cut -d\/ -f3);
78 | DOMAIN=$(echo ${DH} | cut -d\/ -f5);
79 |
80 | if [ -L "${DH}/private_html" ]; then
81 | {
82 | [ "${1}" == "links" ] && echo "[-] Skipping domain ${DOMAIN}";
83 | }
84 | elif [ -d "${DH}/private_html" ]; then
85 | {
86 | if [ "${1}" == "dirs" ]; then
87 | {
88 | mv "${DH}/private_html" "${DH}/private_html.old";
89 | echo "[+] Moved existing private_html to private_html.old for domain ${DOMAIN}";
90 | ln -s public_html ${DH}/private_html;
91 | echo "[+] Created symlink to public_html for domain ${DOMAIN} under ${DH}";
92 | chown -h ${USER}:${USER} ${DH}/private_html;
93 | }
94 | fi;
95 | }
96 | else
97 | {
98 | if [ "${1}" == "no" ]; then
99 | {
100 | ln -s public_html ${DH}/private_html;
101 | chown -h ${USER}:${USER} ${DH}/private_html;
102 | echo "[+] Created symlink to public_html for domain ${DOMAIN} under ${DH}";
103 | }
104 | fi;
105 | }
106 | fi;
107 | done;
108 | }
109 |
110 | case "${1}" in
111 | --list=all|--list)
112 | doList dirs;
113 | doList links;
114 | doList no;
115 | ;;
116 | --list=dirs|--list-dirs)
117 | doList dirs;
118 | ;;
119 | --list=links|--list-links)
120 | doList links;
121 | ;;
122 | --list=no|--list-no)
123 | doList no;
124 | ;;
125 | --create-symlink=dirs)
126 | doCreateSymlink dirs;
127 | ;;
128 | --create-symlink=no)
129 | doCreateSymlink no;
130 | ;;
131 | *)
132 | usage;
133 | ;;
134 | esac;
135 |
136 | exit 0;
137 |
--------------------------------------------------------------------------------
/nginx/README.md:
--------------------------------------------------------------------------------
1 | # directadmin-utils
2 |
3 | A set of scripts for using on Directadmin servers with CustomBuild 2 or as self-standing solutions.
4 | If you need custom installation or support please feel free to request it here or on our site http://www.poralix.com/
5 |
6 | # Structure
7 |
8 | **./nginx/build_nginx** - A script to install either stable or mainline version of NGINX with custombuild2.
9 |
10 | - A version number of NGINX mainline is taken from NGINX's trac site.
11 | - A version number of NGINX stable is taken from the official NGINX's repository for CentOS 7
12 |
13 | **./nginx/build_nginx2** - A script to install a mainline version of NGINX with custombuild2.
14 | A version number of NGINX mainline is taken from versions.txt of Directadmin.
15 |
16 | # Installation of script for NGINX mainline
17 |
18 | for version 1:
19 |
20 | ```
21 | cd /usr/local/directadmin/custombuild/
22 | wget https://raw.githubusercontent.com/poralix/directadmin-utils/master/nginx/build_nginx -O /usr/local/directadmin/custombuild/build_nginx
23 | chmod 755 ./build_nginx
24 | ./build_nginx
25 | ```
26 |
27 | for version 2:
28 |
29 | ```
30 | cd /usr/local/directadmin/custombuild/
31 | wget https://raw.githubusercontent.com/poralix/directadmin-utils/master/nginx/build_nginx2 -O /usr/local/directadmin/custombuild/build_nginx2
32 | chmod 755 ./build_nginx2
33 | ./build_nginx2
34 | ```
35 |
36 | # NGINX 1.13.x with TLSv1.3 and Directadmin
37 |
38 | Instructions: https://help.poralix.com/articles/nginx-with-tlsv1.3-on-directadmin-server
39 |
--------------------------------------------------------------------------------
/nginx/build_nginx:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #######################################################################################
3 | # #
4 | # A script to install a mainline/stable version of NGINX with custombuild2 #
5 | # A version number of NGINX mainline is taken from NGINX's trac site #
6 | # #
7 | #######################################################################################
8 | # #
9 | # Version: 0.4.1 (Fri Dec 16 13:08:32 +07 2022) #
10 | # Written by: Alex S Grebenschikov (zEitEr) #
11 | # Site: www.poralix.com E-mail: support@poralix.com #
12 | # #
13 | #######################################################################################
14 | #######################################################################################
15 | ## #
16 | ## MIT License #
17 | ## #
18 | ## Copyright (c) 2016-2022 Alex S Grebenschikov (www.poralix.com) #
19 | ## #
20 | ## Permission is hereby granted, free of charge, to any person obtaining a copy #
21 | ## of this software and associated documentation files (the "Software"), to deal #
22 | ## in the Software without restriction, including without limitation the rights #
23 | ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell #
24 | ## copies of the Software, and to permit persons to whom the Software is #
25 | ## furnished to do so, subject to the following conditions: #
26 | ## #
27 | ## The above copyright notice and this permission notice shall be included in all #
28 | ## copies or substantial portions of the Software. #
29 | ## #
30 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
31 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
32 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
33 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
34 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #
35 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #
36 | ## SOFTWARE. #
37 | ## #
38 | #######################################################################################
39 |
40 | function usage()
41 | {
42 |
43 | echo "########################################################################";
44 | echo "# #";
45 | echo "# A script to install either a mainline or stable version of NGINX #";
46 | echo "# for Directadmin Custombuild2 #";
47 | echo "# A version of NGINX mainline will be installed by default #";
48 | echo "# Version: 0.4.1 (Fri Dec 16 13:08:32 +07 2022) #";
49 | echo "# Written by: Alex S Grebenschikov (zEitEr) #";
50 | echo "# #";
51 | echo "########################################################################";
52 | echo "";
53 | echo "Usage:";
54 | echo " $0 versions - to update information of available mainline version ";
55 | echo " $0 download - to download the latest available mainline version ";
56 | echo " $0 install - to download and install the latest mainline version";
57 | echo " $0 cron - to run with cron (no installation is done here)";
58 | echo " $0 set-cron - to install a cron-task to run 'cron --${BRANCH}' nightly";
59 | echo "";
60 | echo "Branches (optional):"
61 | echo " --mainline - (default value) actively developed, includes new features";
62 | echo " --stable - stabe version, recieves only bug-fixes";
63 | }
64 |
65 | function update_versions()
66 | {
67 | update_version_stable;
68 | update_version_mainline;
69 |
70 | cd /usr/local/directadmin/custombuild;
71 | cat "custom_versions.txt" | grep -Ev "^nginx:|^nginx_stable:|^nginx_mainline:|^$" > "custom_versions.txt.new";
72 |
73 | if [ "${BRANCH}" == "mainline" ]; then
74 | NGINX_VER="${NGINX_VER_MAINLINE}";
75 | else
76 | NGINX_VER="${NGINX_VER_STABLE}";
77 | fi;
78 |
79 | [ -n "${NGINX_VER_MAINLINE}" ] && echo "nginx_mainline:${NGINX_VER_MAINLINE}:" >> custom_versions.txt.new;
80 | [ -n "${NGINX_VER_STABLE}" ] && echo "nginx_stable:${NGINX_VER_STABLE}:" >> custom_versions.txt.new;
81 | [ -n "${NGINX_VER}" ] && echo "nginx:${NGINX_VER}:" >> "custom_versions.txt.new";
82 |
83 | mv -f "custom_versions.txt.new" "custom_versions.txt";
84 | }
85 |
86 | function update_version_mainline()
87 | {
88 | VERSIONS_FILES="";
89 | VERSIONS_FILES="${VERSIONS_FILES} https://raw.githubusercontent.com/nginx/nginx/master/.hgtags"; # GitHub
90 | VERSIONS_FILES="${VERSIONS_FILES} https://trac.nginx.org/nginx/export/HEAD/nginx/.hgtags"; # TRAC
91 | VERSIONS_FILES="${VERSIONS_FILES} https://hg.nginx.org/nginx/raw-file/tip/.hgtags"; # Official Mercurial Mirror
92 |
93 | # Version number of installed NGINX
94 | NGINX_INSTALLED_VER=$(nginx -v 2>&1 | cut -d\/ -f2);
95 |
96 | for VERSIONS_FILE in ${VERSIONS_FILES};
97 | do
98 | {
99 | NGINX_VER_MAINLINE=$(wget -q ${VERSIONS_FILE} -O - | tail -1 | cut -d\- -f2 | grep -o '[0-9]*\.[0-9]*\.[0-9]*');
100 | [ -n "${NGINX_VER_MAINLINE}" ] && break;
101 | }
102 | done;
103 | }
104 |
105 | function update_version_stable()
106 | {
107 | # Version number of installed NGINX
108 | NGINX_INSTALLED_VER=$(nginx -v 2>&1 | cut -d\/ -f2);
109 | NGINX_VER_STABLE=$(/bin/curl -s http://nginx.org/packages/centos/7/x86_64/RPMS/ | grep -o "nginx-[0-9]*\.[0-9]*\.[0-9]*-[0-9]*\.el7[_0-9]*\.ngx.x86_64.rpm" | cut -d\- -f2 | sort --version-sort | tail -1);
110 |
111 | }
112 |
113 | function show_versions()
114 | {
115 | echo "Latest stable version of Nginx: ${NGINX_VER_STABLE} ${SELECTED_STABLE}";
116 | echo "Latest mainline version of Nginx: ${NGINX_VER_MAINLINE} ${SELECTED_MAINLINE}";
117 | echo "Installed version of Nginx: ${NGINX_INSTALLED_VER}";
118 | }
119 |
120 | function download_nginx()
121 | {
122 | cd /usr/local/directadmin/custombuild;
123 | wget https://nginx.org/download/nginx-${NGINX_VER}.tar.gz -O nginx-${NGINX_VER}.tar.gz;
124 | }
125 |
126 | function install_nginx()
127 | {
128 | cd /usr/local/directadmin/custombuild;
129 | ./build update;
130 |
131 | # Custombuild ignores downloaded packages, and tries to download them again
132 | # so we need to patch it to use already downloaded package
133 | perl -pi -e 's|safeDownloadWithMove "\$\{CWD\}/nginx-|#safeDownloadWithMove "\$\{CWD\}/nginx-|' /usr/local/directadmin/custombuild/build;
134 | perl -pi -e 's|safeDownloadWithMove "\$\{WORKDIR\}/nginx-|#safeDownloadWithMove "\$\{WORKDIR\}/nginx-|' /usr/local/directadmin/custombuild/build;
135 |
136 | ./build nginx;
137 |
138 | # Bring custombuild script back to the original view after we completed nginx installation
139 | perl -pi -e 's|#safeDownloadWithMove "\$\{CWD\}/nginx-|safeDownloadWithMove "\$\{CWD\}/nginx-|' /usr/local/directadmin/custombuild/build;
140 | perl -pi -e 's|#safeDownloadWithMove "\$\{WORKDIR\}/nginx-|safeDownloadWithMove "\$\{WORKDIR\}/nginx-|' /usr/local/directadmin/custombuild/build;
141 | }
142 |
143 | function set_cron()
144 | {
145 | cd /usr/local/directadmin/custombuild/
146 | wget https://raw.githubusercontent.com/poralix/directadmin-utils/master/nginx/build_nginx -O ./build_nginx
147 | chmod 755 ./build_nginx
148 |
149 | touch /etc/cron.d/0build_nginx;
150 | chmod 644 /etc/cron.d/0build_nginx;
151 | echo "21 4 * * * root /usr/local/directadmin/custombuild/build_nginx cron --${BRANCH}" > /etc/cron.d/0build_nginx;
152 | }
153 |
154 | BRANCH="mainline";
155 | SELECTED_MAINLINE="(selected)";
156 | SELECTED_STABLE="";
157 |
158 | for arg in $@;
159 | do
160 | case ${arg} in
161 | --stable)
162 | BRANCH="stable";
163 | SELECTED_MAINLINE="";
164 | SELECTED_STABLE="(selected)";
165 | ;;
166 | --mainline|*)
167 | BRANCH="mainline";
168 | SELECTED_MAINLINE="(selected)";
169 | SELECTED_STABLE="";
170 | ;;
171 | esac;
172 | done;
173 |
174 | case "$1" in
175 | "download")
176 | update_versions;
177 | download_nginx;
178 | ;;
179 | "cron")
180 | update_versions >/dev/null 2>&1;
181 | download_nginx >/dev/null 2>&1;
182 | ;;
183 | "versions")
184 | update_versions;
185 | show_versions;
186 | ;;
187 | "install")
188 | update_versions;
189 | download_nginx;
190 | install_nginx;
191 | ;;
192 | "set-cron")
193 | set_cron;
194 | ;;
195 | *)
196 | usage;
197 | ;;
198 | esac;
199 |
200 | exit 0;
201 |
--------------------------------------------------------------------------------
/nginx/build_nginx2:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #######################################################################################
3 | # #
4 | # A script to install a mainline version of NGINX with custombuild2 #
5 | # A version number of NGINX mainline is taken from versions.txt #
6 | # #
7 | #######################################################################################
8 | # #
9 | # Version: 2.0 (Tue Oct 4 17:06:49 +07 2016) #
10 | # Written by: Alex S Grebenschikov (zEitEr) #
11 | # Site: www.poralix.com E-mail: support@poralix.com #
12 | # #
13 | # #
14 | #######################################################################################
15 | #######################################################################################
16 | ## #
17 | ## MIT License #
18 | ## #
19 | ## Copyright (c) 2016 Alex S Grebenschikov (www.poralix.com) #
20 | ## #
21 | ## Permission is hereby granted, free of charge, to any person obtaining a copy #
22 | ## of this software and associated documentation files (the "Software"), to deal #
23 | ## in the Software without restriction, including without limitation the rights #
24 | ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell #
25 | ## copies of the Software, and to permit persons to whom the Software is #
26 | ## furnished to do so, subject to the following conditions: #
27 | ## #
28 | ## The above copyright notice and this permission notice shall be included in all #
29 | ## copies or substantial portions of the Software. #
30 | ## #
31 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
32 | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
33 | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
34 | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
35 | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #
36 | ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #
37 | ## SOFTWARE. #
38 | ## #
39 | #######################################################################################
40 |
41 |
42 | function read_yes_no()
43 | {
44 | if [ "$1" = "-y" -o "$1" = "y" ]; then
45 | {
46 | yesno="y";
47 | echo "y";
48 | echo "Skipping...as -y was given";
49 | }
50 | elif [ "$1" = "-n" -o "$1" = "n" ]; then
51 | {
52 | yesno="n";
53 | echo "n";
54 | echo "Terminating...as -n was given";
55 | exit 1;
56 | }
57 | fi;
58 |
59 | if [ "$yesno" = "" ]; then
60 | {
61 | while read yesno;
62 | do
63 | {
64 | if [ "$yesno" = "y" ]; then break;
65 | elif [ "$yesno" = "n" ]; then echo "Terminating..."; exit 1;
66 | else echo -n "${ask_text}"; fi;
67 | }
68 | done;
69 | }
70 | fi;
71 | }
72 |
73 | echo "#######################################################################";
74 | echo "# #";
75 | echo "# A script to install a mainline version of NGINX with custombuild2 #";
76 | echo "# A version number of NGINX mainline is taken from versions.txt #";
77 | echo "# Version: 2.0 (Tue Oct 4 17:06:49 +07 2016) #";
78 | echo "# Written by: Alex S Grebenschikov (zEitEr) #";
79 | echo "# #";
80 | echo "#######################################################################";
81 | echo "";
82 |
83 | cd /usr/local/directadmin/custombuild || exit 1;
84 | NGINX_VER=`grep ^nginx_mainline: versions.txt | cut -d\: -f2`;
85 | NGINX_MD5=`grep ^nginx_mainline: versions.txt | cut -d\: -f3`;
86 | NGINX_VER_INSTALLED=`nginx -v 2>&1 | grep 'nginx version' | cut -d\/ -f2`;
87 |
88 | ask_text="Do you want to build NGINX? (y/n): ";
89 |
90 | echo "Latest version of NGINX mainline: ${NGINX_VER}";
91 | echo "Installed version of NGINX: ${NGINX_VER_INSTALLED}";
92 | echo "";
93 | echo -n "${ask_text}";
94 |
95 | [ -e "custom_versions.txt" ] || touch custom_versions.txt;
96 | cat custom_versions.txt | grep -Ev "^nginx:|^$" > custom_versions.txt.new;
97 | mv -f custom_versions.txt.new custom_versions.txt;
98 | echo "nginx:${NGINX_VER}:${NGINX_MD5}" >> custom_versions.txt;
99 |
100 | read_yes_no ${1};
101 |
102 | [ -e "nginx-${NGINX_VER}.tar.gz" ] || wget https://nginx.org/download/nginx-${NGINX_VER}.tar.gz -O nginx-${NGINX_VER}.tar.gz;
103 | ./build update > /dev/null 2>&1;
104 | ./build nginx;
105 |
106 | exit 0;
107 |
--------------------------------------------------------------------------------
/nginx/nginx_reverse/conf/nginx-defaults.conf~TLSv1.3:
--------------------------------------------------------------------------------
1 | default_type application/octet-stream;
2 | tcp_nopush on;
3 | tcp_nodelay on;
4 | sendfile on;
5 |
6 | log_format bytes '$bytes_sent $request_length';
7 |
8 | keepalive_timeout 15;
9 | types_hash_max_size 2048;
10 |
11 | disable_symlinks if_not_owner from=$document_root;
12 |
13 | server_tokens off;
14 |
15 | client_max_body_size 1024m;
16 | client_body_buffer_size 128k;
17 |
18 | server_names_hash_bucket_size 128;
19 | server_names_hash_max_size 10240;
20 |
21 | ssl_dhparam /etc/nginx/ssl.crt/dhparams.pem;
22 |
23 | ssl_session_cache shared:SSL:10m;
24 | ssl_session_timeout 5m;
25 |
26 | # https://mozilla.github.io/server-side-tls/ssl-config-generator/ intermediate configuration.
27 | ssl_protocols TLSv1.2 TLSv1.3;
28 | ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256;
29 | ssl_prefer_server_ciphers on;
30 |
31 | include /etc/nginx/nginx-directoryindex.conf;
32 |
--------------------------------------------------------------------------------
/nginx/nginx_reverse/configure.nginx~openssl-1.1.1:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # Customized by Poralix.com to build NGINX with support of TLSv1.3
4 | # Last modified: Thu Dec 30 12:01:29 +07 2021
5 | #
6 |
7 | OPENSSL_VER="1.1.1m";
8 | OPENSSL_URL="https://www.openssl.org/source/openssl-${OPENSSL_VER}.tar.gz";
9 |
10 | OPENSSL_NAME="openssl_tls_1_3.tar.gz";
11 | wget ${OPENSSL_URL} -O ${OPENSSL_NAME};
12 |
13 | [ -f "${OPENSSL_NAME}" ] && tar -zxvf ${OPENSSL_NAME};
14 | PWD=$(pwd);
15 | OPENSSL_DIR=$(find ${PWD} -type d -name openssl-${OPENSSL_VER}\*);
16 |
17 | ./configure \
18 | "--user=nginx" \
19 | "--group=nginx" \
20 | "--prefix=/usr" \
21 | "--sbin-path=/usr/sbin" \
22 | "--conf-path=/etc/nginx/nginx.conf" \
23 | "--pid-path=/var/run/nginx.pid" \
24 | "--http-log-path=/var/log/nginx/access_log" \
25 | "--error-log-path=/var/log/nginx/error_log" \
26 | "--without-mail_imap_module" \
27 | "--without-mail_smtp_module" \
28 | "--with-http_ssl_module" \
29 | "--with-http_realip_module" \
30 | "--with-http_stub_status_module" \
31 | "--with-http_gzip_static_module" \
32 | "--with-http_dav_module" \
33 | "--with-http_v2_module" \
34 | "--with-http_image_filter_module" \
35 | "--with-openssl=${OPENSSL_DIR}" \
36 | "--with-openssl-opt=enable-tls1_3" \
37 | "--add-module=../ngx_cache_purge" \
38 | "--with-cc-opt='-D FD_SETSIZE=32768'"
39 |
--------------------------------------------------------------------------------
/nginx/nginx_reverse/configure.nginx~openssl-3.0.0:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # Customized by Poralix.com to build NGINX with support of TLSv1.3
4 | # Last modified: Tue Nov 5 08:03:38 CET 2024
5 | #
6 |
7 | # CentOS:
8 | # yum -y install perl-IPC-Cmd gd-devel
9 |
10 | # Debian
11 | # apt -y install libgd-dev
12 |
13 | # Dependences
14 | #
15 | # - libgd-dev/gd-devel is required for http_image_filter_module
16 |
17 | # OpenSSL versions:
18 | #
19 | # openssl-3.3.2.tar.gz 17652kB 03 Sep 2024 13:58
20 | # openssl-3.2.3.tar.gz 17346kB 03 Sep 2024 13:59
21 | # openssl-3.1.7.tar.gz 15317kB 03 Sep 2024 13:59
22 | # openssl-3.0.15.tar.gz 14959kB 03 Sep 2024 14:02
23 |
24 | OPENSSL_VER="3.0.15";
25 | OPENSSL_NAME="openssl_tls_1_3.tar.gz";
26 | WITH_OPENSSL="";
27 |
28 | if [ -f "/root/.custombuild_nginx_openssl" ];
29 | then
30 | OPENSSL_VER=$(head -1 "/root/.custombuild_nginx_openssl");
31 | echo "[INFO] Found OpenSSL version ${OPENSSL_VER} in /root/.custombuild_nginx_openssl";
32 | elif [ -f "/usr/local/directadmin/custombuild/custom_nginx_openssl.txt" ];
33 | then
34 | OPENSSL_VER=$(head -1 "/usr/local/directadmin/custombuild/custom_nginx_openssl.txt");
35 | echo "[INFO] Found OpenSSL version ${OPENSSL_VER} in /usr/local/directadmin/custombuild/custom_nginx_openssl.txt";
36 | fi;
37 |
38 |
39 | WGET_CMD="/usr/bin/wget";
40 | WGET_OPTIONS="";
41 | grep -q -c "CentOS release 6" /etc/redhat-release && WGET_OPTIONS="${WGET_OPTIONS} --no-check-certificate";
42 |
43 | if [ -n "${OPENSSL_VER}" ];
44 | then
45 | #OPENSSL_URL="https://www.openssl.org/source/openssl-${OPENSSL_VER}.tar.gz";
46 | OPENSSL_URL="https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_VER}/openssl-${OPENSSL_VER}.tar.gz";
47 | "${WGET_CMD}" ${WGET_OPTIONS} "${OPENSSL_URL}" -O "${OPENSSL_NAME}"; RETVAL=$?;
48 | fi;
49 |
50 | if [ -f "${OPENSSL_NAME}" ] && [ "${RETVAL}" = "0" ];
51 | then
52 | tar -zxvf ${OPENSSL_NAME};
53 | PWD=$(pwd);
54 | OPENSSL_DIR=$(find "${PWD}" -type d -name "openssl-${OPENSSL_VER}"\*);
55 | [ -d "${OPENSSL_DIR}" ] && WITH_OPENSSL="--with-openssl=${OPENSSL_DIR} --with-openssl-opt=enable-tls1_3";
56 | fi;
57 |
58 | [ -d ./static_modules/modsecurity-nginx ] && modsec_module="--add-module=static_modules/modsecurity-nginx" || modsec_module=""
59 |
60 | # ignore gcc-14 issues
61 | export CFLAGS="${CFLAGS} -fpermissive"
62 |
63 | ./configure \
64 | "--user=nginx" \
65 | "--group=nginx" \
66 | "--prefix=/usr" \
67 | "--sbin-path=/usr/sbin" \
68 | "--conf-path=/etc/nginx/nginx.conf" \
69 | "--pid-path=/var/run/nginx.pid" \
70 | "--http-log-path=/var/log/nginx/access_log" \
71 | "--error-log-path=/var/log/nginx/error_log" \
72 | "--without-mail_imap_module" \
73 | "--without-mail_smtp_module" \
74 | "--with-http_ssl_module" \
75 | "--with-http_realip_module" \
76 | "--with-http_stub_status_module" \
77 | "--with-http_gzip_static_module" \
78 | "--with-http_dav_module" \
79 | "--with-http_v2_module" \
80 | "--with-http_image_filter_module" ${WITH_OPENSSL} \
81 | "--add-module=static_modules/ngx_cache_purge" \
82 | ${modsec_module} \
83 | "--with-cc-opt='-D FD_SETSIZE=32768'"
84 |
--------------------------------------------------------------------------------
/openssl/README.md:
--------------------------------------------------------------------------------
1 | # OpenSSL
2 |
3 | A script to update OpenSSL version on CentOS servers to the latest 1.0.2 version.
4 |
5 | ```
6 | cd /usr/local/directadmin/scripts/
7 | wget https://raw.githubusercontent.com/poralix/directadmin-utils/master/openssl/openssl.install-1.0.2-primary.sh -O openssl.install-1.0.2-primary.sh
8 | chmod 755 openssl.install-1.0.2-primary.sh
9 | ./openssl.install-1.0.2-primary.sh
10 | ```
11 |
12 |
13 | A script to update OpenSSL version on CentOS servers to the latest 1.0.1 version.
14 |
15 | ```
16 | cd /usr/local/directadmin/scripts/
17 | wget https://raw.githubusercontent.com/poralix/directadmin-utils/master/openssl/openssl.install-1.0.1-primary.sh -O openssl.install-1.0.1-primary.sh
18 | chmod 755 openssl.install-1.0.1-primary.sh
19 | ./openssl.install-1.0.1-primary.sh
20 | ```
21 |
22 | # Lock the rpm-package:
23 |
24 | ```
25 | yum -y install yum-plugin-versionlock
26 | yum versionlock openssl-*
27 | ```
28 |
29 | to keep the openssl version away from rpm/yum updates.
30 |
31 | # Error building curl 7.54.0 on Directadmin server against OpenSSL 1.0.2
32 |
33 | Related: https://help.poralix.com/articles/error-building-curl-7.54.0-on-directadmin-with-openssl-1.0.2
34 |
--------------------------------------------------------------------------------
/openssl/openssl.install-1.0.1-primary.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # by Alex Grebenschikov (www.poralix.com)
4 | #
5 | VER="1.0.1";
6 | INSTALL_TO="/usr";
7 |
8 | URL="https://www.openssl.org/source/old/${VER}/openssl-${VER}u.tar.gz"
9 | DIR_TO="/usr/local/src";
10 | SAVE_TO="${DIR_TO}/openssl-${VER}-latest.tar.gz";
11 |
12 | wget ${URL} -O ${SAVE_TO};
13 | tar -zxvf ${SAVE_TO} -C ${DIR_TO};
14 |
15 | cd ${DIR_TO};
16 | DIR=`ls -1d openssl-${VER}*/ | tail -1`;
17 | cd ${DIR};
18 |
19 | ./config --prefix=${INSTALL_TO} no-ssl2 no-ssl3 zlib-dynamic -fPIC shared;
20 | make depend && make install;
21 |
22 | c=`grep "${INSTALL_TO}/lib" /etc/ld.so.conf -c`;
23 | if [ "${c}" == "0" ]; then
24 | echo "${INSTALL_TO}/lib" >> /etc/ld.so.conf;
25 | fi;
26 | ldconfig
27 |
28 | exit 0;
29 |
--------------------------------------------------------------------------------
/openssl/openssl.install-1.0.2-primary.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # by Alex Grebenschikov (www.poralix.com)
4 | #
5 | VER="1.0.2";
6 | INSTALL_TO="/usr";
7 |
8 | URL="https://www.openssl.org/source/openssl-${VER}-latest.tar.gz";
9 | DIR_TO="/usr/local/src";
10 | SAVE_TO="${DIR_TO}/openssl-${VER}-latest.tar.gz";
11 |
12 | wget ${URL} -O ${SAVE_TO};
13 | tar -zxvf ${SAVE_TO} -C ${DIR_TO};
14 |
15 | cd ${DIR_TO};
16 | DIR=`ls -1d openssl-${VER}*/ | tail -1`;
17 | cd ${DIR};
18 |
19 | ./config --prefix=${INSTALL_TO} no-ssl2 no-ssl3 zlib-dynamic -fPIC shared;
20 | make depend && make install;
21 |
22 | c=`grep "${INSTALL_TO}/lib" /etc/ld.so.conf -c`;
23 | if [ "${c}" == "0" ]; then
24 | echo "${INSTALL_TO}/lib" >> /etc/ld.so.conf;
25 | fi;
26 | ldconfig
27 |
28 | exit 0;
29 |
--------------------------------------------------------------------------------
/php/README.md:
--------------------------------------------------------------------------------
1 | # Scripts for operations with PHP
2 |
3 | - php-extension.sh
4 | - bulk_run_php.sh
5 | - change_domain_phpver.sh
6 | - test_sockets_ssl.php
7 |
8 |
9 | # Description of php-extension.sh
10 |
11 | A script to install/update/remove PECL extension for installed by CustomBuild 2.x PHP versions
12 |
13 | Written by: Alex Grebenschikov (support@poralix.com)
14 |
15 | **IMPORTANT**: mod_php is not supported at the moment
16 |
17 | ```
18 | Usage:
19 |
20 | ./php-extension.sh []
21 |
22 | Supported commands:
23 |
24 | install - to install PECL extension
25 | remove - to remove PECL extension
26 | status - show a status of PECL extension for a PHP version
27 | version - show a PECL extension version installed
28 | selfupdate - update this script from GitHub
29 |
30 | Supported options:
31 |
32 | --ver=VER - to install a specified version of an
33 | extension
34 |
35 | --beta - to install a beta version of an extension
36 |
37 | --php=VER - to install extension for one PHP version
38 | digits only (only one version at a time):
39 | 52, 53, 54, 55, 56, 70, 71, 72, 73, 74, 80,
40 | 81, 82, 83 etc
41 |
42 | --verbose - show messages from configure/make operations
43 |
44 | ```
45 |
46 | # Description of bulk_run_php.sh
47 |
48 | A script to run code with all existing PHP versions installed by CustomBuild 2.x
49 |
50 | ```
51 | Usage:
52 | ./bulk_run_php.sh
53 |
54 | Built-in commands:
55 | versions - to list installed PHP versions
56 | full-versions - to show installed PHP versions
57 | build - to re-install all installed versions (expert mode is used)
58 | update - to update all installed versions (expert mode is used)
59 | --ini - to show loaded ini files for PHP
60 |
61 | Build all (beta):
62 | DO NOT use it for mod_php!!!
63 | you can specify: suphp, fastcgi, php-fpm to force the mode
64 |
65 | Update all (beta):
66 | DO NOT use it for mod_php!!!
67 | you can specify: suphp, fastcgi, php-fpm to force the mode
68 |
69 | Other commands:
70 | You can run any other command supported by PHP,
71 | run
72 | php --help
73 | or
74 | ./bulk_run_php.sh --help
75 | to see a list of the options.
76 | ```
77 |
78 | # Description of change_domain_phpver.sh
79 |
80 | The script can be used to show which PHP version is set for a domain in Directadmin.
81 |
82 | You can use the script to change PHP version for a domain from pre-installed with Custombuild 2.0.
83 |
84 | Example of usage:
85 |
86 | ```
87 | # ./change_domain_phpver.sh domain.com
88 | Domain domain.com found and is owned by the user userbob
89 | Currently used: (no values mean defaults)
90 | php1_select: 5.3 as suphp (2)
91 | php2_select: 5.6 as suphp (1)
92 | PHP Versions:
93 | 1 stands for PHP (default): 5.6 as suphp
94 | 2 stands for PHP (additional): 5.3 as suphp
95 | You did not specified new version, terminating here...
96 | ```
97 |
98 | Run
99 |
100 | ```
101 | ./change_domain_phpver.sh domain.com 2
102 | ```
103 |
104 | to set the second PHP version as a default for the domain.com (in our case it's PHP 5.3).
105 |
106 | Run
107 |
108 | ```
109 | ./change_domain_phpver.sh domain.com 1
110 | ```
111 |
112 | to set the primary PHP version as a default for the domain.com (in our case it's PHP 5.6).
113 |
114 | # Description of test_sockets_ssl.php
115 |
116 | A simple PHP-script to test connections to a remote host with and/or without TLS/SSL.
117 |
118 | Run under Document Root via HTTP/HTTPS or in a console:
119 |
120 | ```
121 | # php test_sockets_ssl.php
122 |
123 | Connection to imap.gmail.com:993 without SSL FAILED
124 | Connection to imap.gmail.com:993 with SSL FAILED
125 | Connection to smtp.gmail.com:25 without SSL FAILED
126 | Connection to smtp.gmail.com:25 with SSL OK
127 | Connection to smtp.gmail.com:465 without SSL FAILED
128 | Connection to smtp.gmail.com:465 with SSL FAILED
129 | Connection to smtp.gmail.com:587 without SSL FAILED
130 | Connection to smtp.gmail.com:587 with SSL OK
131 |
132 | ```
133 |
--------------------------------------------------------------------------------
/php/bulk_run_php.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # =====================================================
3 | # A script to run code with PHP versions
4 | # installed by CustomBuild 2.x
5 | # =====================================================
6 | # Written by Alex Grebenschikov(support@poralix.com)
7 | # =====================================================
8 | # versions: 0.4-beta $ Tue May 15 16:47:43 +07 2018
9 | # 0.3-beta $ Tue May 15 14:15:13 +07 2018
10 | # 0.2-beta $ Mon Dec 26 14:32:03 +07 2016
11 | # 0.1-beta $ Tue Mar 17 12:40:51 NOVT 2015
12 | # =====================================================
13 | #set -x
14 |
15 | LANG=C;
16 | CMD="";
17 | PHPVER="";
18 | BN="`tput -Txterm bold`"
19 | BF="`tput -Txterm sgr0`"
20 |
21 | do_usage()
22 | {
23 | echo "
24 | # =====================================================
25 | # A script to run code with PHP versions
26 | # installed by CustomBuild 2.x
27 | # =====================================================
28 | # Written by Alex Grebenschikov(support@poralix.com)
29 | # =====================================================
30 |
31 | Usage:
32 | $0
33 |
34 | Built-in commands:
35 | versions - to list installed PHP versions
36 | full-versions - to show installed PHP versions
37 | build - to re-install all installed versions (expert mode is used)
38 | update - to update all installed versions (expert mode is used)
39 | --ini - to show loaded ini files for PHP
40 |
41 | Build all (beta):
42 | DO NOT use it for mod_php!!!
43 | you can specify: suphp, fastcgi, php-fpm to force the mode
44 |
45 | Update all (beta):
46 | DO NOT use it for mod_php!!!
47 | you can specify: suphp, fastcgi, php-fpm to force the mode
48 |
49 | Other commands:
50 | You can run any other command supported by PHP,
51 | run
52 | php --help
53 | or
54 | $0 --help
55 | to see a list of the options.
56 | ";
57 | }
58 |
59 | # Do the version investigation and update if it's requested
60 | do_versions()
61 | {
62 | PHP_MODE="${1}";
63 | PHP_DIR=`dirname ${PHP}`;
64 | IVER=`${PHP} -v 2>&1 | grep ^PHP.*built | awk '{print $2}'`;
65 | IVER_xx=`echo ${IVER} | awk -F '.' '{print $1$2}'`;
66 | IVER_xdx=`echo ${IVER} | awk -F '.' '{print $1"."$2}'`;
67 | AVER=`grep ^php${IVER_xx}: /usr/local/directadmin/custombuild/versions.txt | cut -d\: -f2`;
68 |
69 | DETECTED=0; # 0 - none, 1 - custombuild, 2 - autodetected
70 | RELEASE_VERSION='';
71 |
72 | OPTIONS_CONF="/usr/local/directadmin/custombuild/options.conf";
73 | if [ -z "${PHP_MODE}" ]; then
74 | c=$(egrep -c -m1 "^php[1,2]_release=${IVER_xdx}" "${OPTIONS_CONF}");
75 | if [ "${c}" == "1" ]; then
76 | RELEASE_VERSION=$(egrep "^php[0-9]_release=${IVER_xdx}" "${OPTIONS_CONF}" | cut -d\_ -f1);
77 | PHP_MODE=$(grep "${RELEASE_VERSION}_mode" "${OPTIONS_CONF}" | cut -d\= -f2);
78 | DETECTED=1;
79 | fi;
80 | fi;
81 |
82 | if [ -z "${PHP_MODE}" ]; then
83 | PHP_MODE="mod_php";
84 | if [ -e "${PHP_DIR}/lsphp" ]; then
85 | PHP_MODE="lsphp";
86 | DETECTED=2;
87 | elif [ -e "/usr/local/php${IVER_xx}/etc/php-fpm.conf" ]; then
88 | PHP_MODE="php-fpm";
89 | DETECTED=2;
90 | elif [ -e "/usr/local/safe-bin/fcgid${IVER_xx}.sh" ]; then
91 | PHP_MODE="fastcgi";
92 | DETECTED=2;
93 | elif [ -e "/usr/local/suphp/sbin/suphp" ]; then
94 | PHP_MODE="suphp";
95 | DETECTED=2;
96 | fi;
97 | fi;
98 |
99 | UPDATE="";
100 | echo "";
101 | if [ -n "${AVER}" ]; then
102 | echo "Latest version of PHP ${IVER_xdx}: ${BN}${AVER}${BF}";
103 | if [ "${AVER}" != "${IVER}" ]; then
104 | UPDATE="${BN}Update is available${BF}";
105 | UPDATE="${UPDATE}\nTo update run: ${BN}cd /usr/local/directadmin/custombuild && ./build php_expert ${IVER_xdx} ${PHP_MODE}${BF}";
106 | else
107 | UPDATE="To re-install run: ${BN}cd /usr/local/directadmin/custombuild && ./build php_expert ${IVER_xdx} ${PHP_MODE}${BF}";
108 | fi;
109 | else
110 | echo "Latest version of PHP ${IVER_xdx}: N/A";
111 | fi;
112 | case ${DETECTED} in
113 | 0)
114 | DETECTED_LANG="not found";
115 | ;;
116 | 1)
117 | DETECTED_LANG="found in custombuild as ${RELEASE_VERSION}";
118 | ;;
119 | 2)
120 | DETECTED_LANG="auto detection";
121 | ;;
122 | esac;
123 | echo "Installed version of PHP ${IVER_xdx}: ${BN}${IVER}${BF} as ${BN}${PHP_MODE}${BF} (${DETECTED_LANG})";
124 | echo "Installed into ${BN}${PHP}${BF}";
125 | [ -n "${UPDATE}" ] && echo -e "${UPDATE}";
126 | }
127 |
128 | # Call to PHP for version number
129 | do_full_versions()
130 | {
131 | ${PHP} -v 2>&1 | grep ^PHP;
132 | }
133 |
134 | # Call to custombuild
135 | do_update()
136 | {
137 | cd /usr/local/directadmin/custombuild && ./build php_expert ${IVER_xdx} ${PHP_MODE};
138 | }
139 |
140 | # Build all installed PHP versions
141 | do_build_all()
142 | {
143 | do_versions >/dev/null 2>&1;
144 | if [ "${PHP_MODE}" != "mod_php" ]; then
145 |
146 | if [ -n "${1}" ]; then
147 | case "${1}" in
148 | suphp|fastcgi|php-fpm)
149 | PHP_MODE="${1}";
150 | ;;
151 | *)
152 | ;;
153 | esac;
154 | fi;
155 |
156 | echo "Re-installing version of PHP ${IVER_xdx}: ${BN}${IVER}${BF} as ${BN}${PHP_MODE}${BF}";
157 | echo "Installed into ${BN}${PHP}${BF}";
158 | echo "Will run /usr/local/directadmin/custombuild && ./build php_expert ${IVER_xdx} ${PHP_MODE}";
159 | do_update ${PHP_MODE};
160 | echo "";
161 | else
162 | echo "DON'T USE THE SCRIPT FOR UPDATING PHP INSTALLED AS mod_PHP";
163 | fi;
164 | }
165 |
166 | # Update all installed PHP versions
167 | do_update_all()
168 | {
169 | do_versions >/dev/null 2>&1;
170 | if [ "${AVER}" != "${IVER}" ]; then
171 | if [ "${PHP_MODE}" != "mod_php" ]; then
172 |
173 | if [ -n "${1}" ]; then
174 | case "${1}" in
175 | suphp|fastcgi|php-fpm)
176 | PHP_MODE="${1}";
177 | ;;
178 | *)
179 | ;;
180 | esac;
181 | fi;
182 |
183 | echo "Updating version of PHP ${IVER_xdx}: ${BN}${IVER}${BF} as ${BN}${PHP_MODE}${BF}";
184 | echo "Installed into ${BN}${PHP}${BF}";
185 | echo "Will run /usr/local/directadmin/custombuild && ./build php_expert ${IVER_xdx} ${PHP_MODE}";
186 | do_update ${PHP_MODE};
187 | echo "";
188 | else
189 | echo "DON'T USE THE SCRIPT FOR UPDATING PHP INSTALLED AS mod_PHP";
190 | fi;
191 | fi;
192 | }
193 |
194 | do_other()
195 | {
196 | echo "${BN}Running for ${PHPVER}${BF}";
197 | ${PHP} $@;
198 | echo "";
199 | }
200 |
201 | if [ ! -x "/usr/local/directadmin/directadmin" ]; then
202 | echo "Directadmin not found! Terminating...";
203 | exit 1;
204 | fi;
205 |
206 | if [ -z "$1" ];
207 | then
208 | do_usage;
209 | exit 2;
210 | else
211 | CMD=$1;
212 | fi;
213 |
214 | for PHP in `ls -1 /usr/local/php*/bin/php | egrep "\/php[0-9]{2}\/bin" | sort -n`;
215 | do
216 | PHPVER=`echo ${PHP} | cut -d\/ -f4`;
217 |
218 | case "${CMD}" in
219 | versions|version)
220 | do_versions;
221 | ;;
222 | full-versions|full-version)
223 | do_full_versions;
224 | ;;
225 | build)
226 | do_build_all $2;
227 | ;;
228 | update)
229 | do_update_all $2;
230 | ;;
231 | *)
232 | do_other $@;
233 | ;;
234 | esac;
235 | done;
236 |
237 | echo "";
238 |
239 | exit 0;
240 |
--------------------------------------------------------------------------------
/php/change_domain_phpver.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # A script to change domain's PHP version in console
4 | # ======================================================
5 | # Written by Alex s Grebenschikov (support@poralix.com)
6 | # Version: 0.1-beta $ Mon Dec 14 00:50:41 NOVT 2015
7 | # ======================================================
8 |
9 | BN="`tput -Txterm bold`"
10 | BF="`tput -Txterm sgr0`"
11 |
12 | do_show_phpver()
13 | {
14 | if [ "$1" == "1" ];
15 | then
16 | echo "${BN}${php_release[1]}${BF} as ${BN}${php_mode[1]}${BF}";
17 | elif [ "$1" == "2" ];
18 | then
19 | echo "${BN}${php_release[2]}${BF} as ${BN}${php_mode[2]}${BF}";
20 | else
21 | echo "";
22 | fi;
23 | }
24 |
25 | do_versions()
26 | {
27 | echo -e "\t${BN}1${BF} stands for PHP (default): `do_show_phpver 1`";
28 | echo -e "\t${BN}2${BF} stands for PHP (additional): `do_show_phpver 2`";
29 | }
30 |
31 | do_usage()
32 | {
33 | echo "#######################################################";
34 | echo "# Written by Alex S Grebenschikov #";
35 | echo "#######################################################";
36 | echo "Usage ${BN}$0 [<1|2>]${BF}";
37 | echo "PHP Versions (if omitted will show current settings): ";
38 | do_versions;
39 | exit 0;
40 | }
41 |
42 | data=`grep "^php[1,2]_" /usr/local/directadmin/custombuild/options.conf`;
43 | php_release[1]=`echo $data | grep -o php1_release=[^\ ]* | cut -d\= -f2`
44 | php_mode[1]=`echo $data | grep -o php1_mode=[^\ ]* | cut -d\= -f2`
45 | php_release[2]=`echo $data | grep -o php2_release=[^\ ]* | cut -d\= -f2`
46 | php_mode[2]=`echo $data | grep -o php2_mode=[^\ ]* | cut -d\= -f2`
47 |
48 | if [ -z "$1" ];
49 | then
50 | do_usage;
51 | else
52 | DOMAIN=$1;
53 | fi;
54 |
55 | DO_NOT_CHANGE=0;
56 |
57 | if [ -n "$2" ];
58 | then
59 | if [ "$2" == "1" ];
60 | then
61 | PHP1_VER=$2;
62 | PHP2_VER=2;
63 | elif [ "$2" == "2" ];
64 | then
65 | PHP1_VER=$2;
66 | PHP2_VER=1;
67 | else
68 | do_usage;
69 | fi;
70 | else
71 | DO_NOT_CHANGE=1
72 | fi;
73 |
74 | DCF=`ls -1 /usr/local/directadmin/data/users/*/domains/${DOMAIN}.conf 2>&1 | head -1`;
75 |
76 | if [ ! -f "${DCF}" ];
77 | then
78 | echo "[ERROR] Domain ${BN}${DOMAIN}${BF} does not seem to exist on the server!";
79 | exit 1;
80 | fi;
81 |
82 | owner=`echo ${DCF} | cut -d\/ -f7`
83 |
84 | echo "Domain ${BN}${DOMAIN}${BF} found and is owned by the user ${BN}${owner}${BF}";
85 |
86 | data=`grep "^php[1,2]_select=" ${DCF}`;
87 | php1_select=`echo $data | grep -o php1_select=[^\ ]* | cut -d\= -f2`
88 | php2_select=`echo $data | grep -o php2_select=[^\ ]* | cut -d\= -f2`
89 |
90 | echo "Currently used: (no values mean defaults)";
91 | echo -e "\tphp1_select: `do_show_phpver ${php1_select}` (${php1_select})";
92 | echo -e "\tphp2_select: `do_show_phpver ${php2_select}` (${php2_select})";
93 | echo "PHP Versions: ";
94 | do_versions;
95 |
96 | if [ "${DO_NOT_CHANGE}" == "1" ];
97 | then
98 | echo "You did not specified new version, terminating here...";
99 | exit 0;
100 | fi;
101 |
102 | if [ -z ${php1_select} ] && [ -z ${php2_select} ];
103 | then
104 | echo "php1_select=${PHP1_VER}" >> ${DCF};
105 | echo "php2_select=${PHP2_VER}" >> ${DCF};
106 | else
107 | TF=`mktemp`;
108 | cat ${DCF}| grep -v "^php[1,2]_select=" > ${TF};
109 | cat ${TF} > ${DCF};
110 | echo "php1_select=${PHP1_VER}" >> ${DCF};
111 | echo "php2_select=${PHP2_VER}" >> ${DCF};
112 | rm -f ${TF};
113 | fi;
114 |
115 | echo "Rewriting virtual host....";
116 | echo "action=rewrite&value=httpd&user=${owner}" >> /usr/local/directadmin/data/task.queue
117 | /usr/local/directadmin/dataskq
118 | /usr/local/directadmin/dataskq
119 | echo "Finished...";
120 |
121 | exit 0;
122 |
--------------------------------------------------------------------------------
/php/php-extension.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # ======================================================
3 | #
4 | # A script to install/update/remove PHP extensions
5 | # for all installed by CustomBuild 2.x PHP versions
6 | # Written by Alex Grebenschikov (support@poralix.com)
7 | #
8 | # ======================================================
9 | # Version: 0.17.4-beta $ Wed May 7 18:21:48 +07 2025
10 | # Created: 0.2-beta $ Tue Mar 17 12:40:51 NOVT 2015
11 | # ======================================================
12 | #
13 | #set -x
14 |
15 | PWD="$(pwd)";
16 | WORKDIR="/usr/local/src";
17 | LANG=C;
18 | FILE="";
19 | EXT="";
20 | BN="$(tput -Txterm bold)"
21 | BF="$(tput -Txterm sgr0)"
22 |
23 | redirect_cmd()
24 | {
25 | if [ "${QUIET}" == "1" ];
26 | then
27 | "$@" > /dev/null 2>&1;
28 | else
29 | "$@";
30 | fi;
31 | return "$?";
32 | }
33 |
34 | verify_php_version()
35 | {
36 | local loc_php_version loc_pecl_bin;
37 | loc_php_version="${1}";
38 |
39 | if [ -n "${loc_php_version}" ];
40 | then
41 | {
42 | if [ ! -d "/usr/local/php${loc_php_version}/" ] || [ ! -f "/usr/local/php${loc_php_version}/bin/php" ];
43 | then
44 | {
45 | echo "${BN}[ERROR] PHP version php${loc_php_version} was not found!${BF}";
46 | exit 2;
47 | }
48 | fi;
49 |
50 | loc_pecl_bin="/usr/local/php${loc_php_version}/bin/pecl";
51 | if [ ! -x "${loc_pecl_bin}" ]; then
52 | echo "${BN}[ERROR] PECL for PHP version php${loc_php_version} was not found!${BF}";
53 | exit 2;
54 | fi;
55 | }
56 | fi;
57 | }
58 |
59 | find_extension_version()
60 | {
61 | local loc_php_version loc_php_dotver;
62 | loc_php_version="${1:?}";
63 | loc_php_dotver=$(echo "${loc_php_version}" | egrep -o '(5|7|8|9)[0-9]+' | sed 's/\(.\)\(.\)/\1.\2/'); #'
64 |
65 | if [ -z "${EXT_VERSION}" ];
66 | then
67 | {
68 | case "${loc_php_version}" in
69 | 52|53|54|55|56)
70 | case "${EXT}" in
71 | apcu)
72 | EXT_VERSION_LEGACY="4.0.11";
73 | ;;
74 | igbinary)
75 | EXT_VERSION_LEGACY="2.0.8";
76 | ;;
77 | redis)
78 | EXT_VERSION_LEGACY="3.1.6";
79 | ;;
80 | *)
81 | EXT_VERSION_LEGACY="";
82 | ;;
83 | esac;
84 | ;;
85 | 70|71|72|73)
86 | case "${EXT}" in
87 | redis)
88 | EXT_VERSION_LEGACY="5.3.7";
89 | ;;
90 | *)
91 | EXT_VERSION_LEGACY="";
92 | ;;
93 | esac;
94 | ;;
95 | *)
96 | case "${EXT}" in
97 | redis)
98 | EXT_VERSION_LEGACY="";
99 | if [ "${IS_CENTOS_7}" == "1" ];
100 | then
101 | {
102 | EXT_VERSION_LEGACY="5.3.7";
103 | }
104 | fi;
105 | ;;
106 | *)
107 | EXT_VERSION_LEGACY="";
108 | ;;
109 | esac;
110 | ;;
111 | esac;
112 | }
113 | fi;
114 | test -n "${EXT_VERSION_LEGACY}" && echo "${BN}[OK] Using legacy version=${EXT_VERSION_LEGACY} for extension=${EXT} for PHP ${loc_php_dotver}${BF}";
115 | test -z "${EXT_VERSION_LEGACY}" && echo "${BN}[OK] Using default version for extension=${EXT} for PHP ${loc_php_dotver}${BF}";
116 | }
117 |
118 | do_install_sourceguardian()
119 | {
120 | if [ "${SOURCEGUARDIAN_INSTALLED}" == "1" ];
121 | then
122 | echo "${BN}[OK] Already installed sourceguardian loaders${BF}";
123 | return 0;
124 | fi;
125 |
126 | echo "${BN}[OK] Going to download sourceguardian loaders${BF}";
127 | mkdir -p "${SOURCEGUARDIAN_DIR}";
128 | cd "${SOURCEGUARDIAN_DIR}" && curl -s https://www.sourceguardian.com/loaders/download/loaders.linux-x86_64.tar.gz --output "${SOURCEGUARDIAN_DIR}/loaders.linux-x86_64.tar.gz";
129 | if [ "$?" == "0" ] && [ -f "${SOURCEGUARDIAN_DIR}/loaders.linux-x86_64.tar.gz" ];
130 | then
131 | {
132 | echo "${BN}[OK] Unpacking sourceguardian loaders to ${SOURCEGUARDIAN_DIR}${BF}";
133 | cd "${SOURCEGUARDIAN_DIR}" && tar -xzf "${SOURCEGUARDIAN_DIR}/loaders.linux-x86_64.tar.gz";
134 | if [ "$?" == "0" ];
135 | then
136 | {
137 | SOURCEGUARDIAN_INSTALLED=1;
138 | rm -f "${SOURCEGUARDIAN_DIR}/loaders.linux-x86_64.tar.gz";
139 | }
140 | else
141 | {
142 | SOURCEGUARDIAN_INSTALLED=0;
143 | echo "${BN}[ERROR] Failed to unpack sourceguardian loaders${BF}";
144 | exit 1;
145 | }
146 | fi;
147 | }
148 | else
149 | {
150 | SOURCEGUARDIAN_INSTALLED=0;
151 | echo "${BN}[ERROR] Failed to download sourceguardian loaders${BF}";
152 | exit 1;
153 | }
154 | fi;
155 | }
156 |
157 | do_usage()
158 | {
159 | echo "
160 | # ============================================================ #
161 | # A script to install/update/remove PHP extensions #
162 | # for all installed by CustomBuild 2.x PHP versions #
163 | # ============================================================ #
164 | # IMPORTANT: DirectAdmin servers are only supported #
165 | # ============================================================ #
166 | # Written by Alex Grebenschikov(support@poralix.com) #
167 | # Version: 0.17.4-beta $ Wed May 7 18:21:48 +07 2025 #
168 | # ============================================================ #
169 |
170 | Usage:
171 |
172 | $0 []
173 |
174 | Supported commands:
175 |
176 | install - to install PECL extension
177 | remove - to remove PECL extension
178 | status - show a status of PECL extension for a PHP version
179 | version - show a PECL extension version installed
180 | selfupdate - update this script from GitHub
181 |
182 | Supported options:
183 |
184 | --ver=VER - to install a specified version of an
185 | extension
186 |
187 | --beta - to install a beta version of an extension
188 |
189 | --php=VER - to install extension for one PHP version
190 | digits only (only one version at a time):
191 | 52, 53, 54, 55, 56, 70, 71, 72, 73, 74, 80,
192 | 81, 82, 83, 84 etc
193 |
194 | --verbose - show messages from configure/make operations
195 | ";
196 |
197 | exit 1;
198 | }
199 |
200 | do_disable_extension_in_da()
201 | {
202 | local loc_php_version loc_php_da_ini_file;
203 | loc_php_version="${1:?}";
204 | loc_php_da_ini_file="/usr/local/php${loc_php_version}/lib/php.conf.d/10-directadmin.ini";
205 | if grep -q "^php_${EXT}=yes$" /usr/local/directadmin/custombuild/options.conf;
206 | then
207 | echo "${BN}[OK] Disabling ${EXT} for PHP in DirectAdmin CustomBuild${BF}";
208 | /usr/local/directadmin/directadmin build set php_${EXT} no;
209 | else
210 | if grep -q "^php_${EXT}=no$" /usr/local/directadmin/custombuild/options.conf;
211 | then
212 | echo "${BN}[NOTICE] ${EXT} for PHP is already disabled in DirectAdmin CustomBuild${BF}";
213 | else
214 | echo "${BN}[NOTICE] ${EXT} for PHP is not managed by DirectAdmin CustomBuild${BF}";
215 | fi;
216 | fi;
217 | if grep -q "^extension=${EXT}.so$" "${loc_php_da_ini_file}";
218 | then
219 | echo "${BN}[OK] Disabling ${EXT} in PHP ${loc_php_version} installed by DirectAdmin CustomBuild${BF}";
220 | perl -pi -e "s/^extension=${EXT}.so//" "${loc_php_da_ini_file}";
221 | fi;
222 | }
223 |
224 | do_update()
225 | {
226 | local loc_php_version loc_php_bindir loc_pecl_bin loc_phpize_bin loc_php_dotver loc_configure_options loc_extension_dir;
227 | loc_php_version="${1:?}";
228 | loc_php_bindir="/usr/local/php${loc_php_version}/bin";
229 | loc_pecl_bin="/usr/local/php${loc_php_version}/bin/pecl";
230 | loc_phpize_bin="/usr/local/php${loc_php_version}/bin/phpize";
231 | loc_php_dotver=$(echo "${loc_php_version}" | egrep -o '(5|7|8|9)[0-9]+' | sed 's/\(.\)\(.\)/\1.\2/'); #'
232 | loc_extension_dir=$("/usr/local/php${loc_php_version}/bin/php" -i 2>&1 | grep "^extension_dir" | awk '{print $3}');
233 | loc_configure_options='';
234 |
235 | case "${EXT}" in
236 | redis)
237 | loc_configure_options="--enable-redis-lzf";
238 | test -e /usr/include/zstd.h && loc_configure_options="${loc_configure_options} --enable-redis-zstd";
239 | test -e "${loc_extension_dir}/igbinary.so" && loc_configure_options="${loc_configure_options} --enable-redis-igbinary";
240 | ;;
241 | igbinary)
242 | loc_configure_options="";
243 | ;;
244 | *)
245 | loc_configure_options='';
246 | ;;
247 | esac;
248 |
249 | if [ -x "${loc_phpize_bin}" ];
250 | then
251 | {
252 | EXT_FULL="${EXT}";
253 | if [ -z "${EXT_VERSION_LEGACY}" ];
254 | then
255 | {
256 | if [ "${BETA}" == "1" ]; then
257 | EXT_FULL="${EXT}-beta";
258 | elif [ -n "${EXT_VERSION}" ]; then
259 | EXT_FULL="${EXT}-${EXT_VERSION}";
260 | fi;
261 | }
262 | else
263 | {
264 | EXT_FULL="${EXT}-${EXT_VERSION_LEGACY}";
265 | }
266 | fi;
267 |
268 | tmpdir=$(mktemp -d "${WORKDIR}/tmp.XXXXXXXXXX");
269 | tmpfile=$(mktemp "${WORKDIR}/tmp.XXXXXXXXXX");
270 |
271 | echo "${BN}[OK] Updating ${loc_pecl_bin}${BF}";
272 | redirect_cmd "${loc_pecl_bin}" channel-update pecl.php.net;
273 | echo "${BN}[OK] Downloading ${EXT_FULL} for PHP ${loc_php_dotver}${BF}";
274 | "${loc_pecl_bin}" download "${EXT_FULL}" 2>&1 | tee "${tmpfile}";
275 | FILE=$(grep "^File" "${tmpfile}" | grep downloaded | cut -d\ -f2);
276 | rm -f "${tmpfile}";
277 |
278 | if [ -f "${FILE}" ];
279 | then
280 | {
281 | echo "${BN}[OK] Going to install extension ${EXT} for PHP ${loc_php_dotver}${BF}";
282 |
283 | cd "${WORKDIR}";
284 | rm -rfv "${tmpdir:?}"/*;
285 | tar -zxf "${FILE}" --directory="${tmpdir}";
286 | DIR=$(find "${tmpdir}/${EXT}"* -type d | head -1);
287 | if [ -d "${DIR}" ];
288 | then
289 | {
290 | cd "${DIR}";
291 | echo "${BN}[OK] Configuring ${EXT_FULL} for PHP ${loc_php_dotver}${BF}";
292 | redirect_cmd "${loc_phpize_bin}";
293 | redirect_cmd ./configure ${loc_configure_options} "--with-php-config=${loc_php_bindir}/php-config";
294 | RETVAL=$?;
295 | if [ "${RETVAL}" == "0" ];
296 | then
297 | {
298 | echo "${BN}[OK] Compiling ${EXT_FULL} for PHP ${loc_php_dotver}${BF}";
299 | redirect_cmd make && redirect_cmd make install;
300 | RETVAL=$?;
301 | if [ "${RETVAL}" == "0" ];
302 | then
303 | {
304 | echo "${BN}[OK] Installation of ${EXT} for PHP ${loc_php_dotver} completed!${BF}";
305 | do_disable_extension_in_da "${loc_php_version}";
306 | }
307 | else
308 | {
309 | echo "${BN}[ERROR] Installation of ${EXT} for PHP ${loc_php_dotver} failed${BF}";
310 | }
311 | fi;
312 | echo -ne '\007';
313 | }
314 | else
315 | {
316 | echo "${BN}[ERROR] Configure of ${EXT} for PHP ${loc_php_dotver} failed${BF}";
317 | }
318 | fi;
319 | cd "${WORKDIR}";
320 | }
321 | fi;
322 | }
323 | else
324 | {
325 | echo "${BN}[ERROR] Failed to download extension file of ${EXT} for PHP ${loc_php_dotver}${BF}";
326 | }
327 | fi;
328 | }
329 | else
330 | {
331 | echo "ERROR! Executable ${loc_phpize_bin} not found!";
332 | exit 1;
333 | }
334 | fi;
335 | rm -rf "${tmpdir}";
336 | }
337 |
338 | do_update_ini()
339 | {
340 | local loc_php_version loc_php_dotver loc_extension_dir loc_php_inidir loc_php_inifile loc_inifile;
341 | loc_php_version="${1:?}";
342 | loc_php_dotver=$(echo "${loc_php_version}" | egrep -o '(5|7|8|9)[0-9]+' | sed 's/\(.\)\(.\)/\1.\2/'); #'
343 | loc_extension_dir=$("/usr/local/php${loc_php_version}/bin/php" -i 2>&1 | grep "^extension_dir" | awk '{print $3}');
344 |
345 | loc_php_inidir="/usr/local/php${1}/lib/php.conf.d";
346 | test -d "${loc_php_inidir}" || mkdir -p "${loc_php_inidir}";
347 |
348 | loc_inifile=${2:-custom};
349 | loc_php_inifile="${loc_php_inidir}/99-${loc_inifile}.ini";
350 | test -f "${loc_php_inifile}" || loc_php_inifile="${loc_php_inidir}/90-${loc_inifile}.ini";
351 |
352 | if [ "${EXT}" == "sourceguardian" ];
353 | then
354 | {
355 | if [ -f "${SOURCEGUARDIAN_DIR}/ixed.${loc_php_dotver}.lin" ];
356 | then
357 | {
358 | echo "${BN}[OK] Found ${EXT}. Enabling the extension in ${loc_php_inifile}${BF}";
359 | echo "; Created by $0 script" > "${loc_php_inifile}";
360 | echo "[sourceguardian]" >> "${loc_php_inifile}";
361 | echo "zend_extension=${SOURCEGUARDIAN_DIR}/ixed.${loc_php_dotver}.lin" >> "${loc_php_inifile}";
362 | }
363 | else
364 | {
365 | echo "${BN}[WARNING] Could not found ${EXT}. Removing the extension from ${loc_php_inifile}${BF}";
366 | rm -f "${loc_php_inifile}";
367 | }
368 | fi;
369 | }
370 | else
371 | {
372 | case "${EXT}" in
373 | xdebug)
374 | ROW="zend_extension=${EXT}.so";
375 | ;;
376 | *)
377 | ROW="extension=${EXT}.so";
378 | ;;
379 | esac;
380 |
381 | if [ -f "${loc_extension_dir}/${EXT}.so" ];
382 | then
383 | {
384 | echo "${BN}[OK] Found ${EXT}.so. Enabling the extension in ${loc_php_inifile}${BF}";
385 | grep -m1 -q "^${ROW}" "${loc_php_inifile}" >/dev/null 2>&1 || echo "${ROW}" >> "${loc_php_inifile}";
386 | "/usr/local/php${1}/bin/php" -i 2>&1 | grep -i "^${EXT}" | grep -v 'Configure Command' | head -3;
387 | }
388 | else
389 | {
390 | while read -r INI_FILE;
391 | do
392 | echo "${BN}[WARNING] Could not find ${loc_extension_dir}/${EXT}.so. Removing extension from ${INI_FILE}${BF}";
393 | grep -m1 -q "^${ROW}" "${INI_FILE}" && perl -pi -e "s#^${ROW}\n##" "${INI_FILE}";
394 | grep -m1 -q "^${ROW}" "${INI_FILE}" && perl -pi -e "s#^${ROW}##" "${INI_FILE}";
395 | done < <(find "${loc_php_inidir}/"*.ini);
396 | }
397 | fi;
398 | }
399 | fi;
400 | unset INI_FILE;
401 | unset ROW;
402 | }
403 |
404 | do_remove()
405 | {
406 | local loc_php_versions loc_php_version loc_extension_dir loc_extension_file loc_php_dotver;
407 |
408 | if [ -n "${PVN}" ]; then
409 | {
410 | loc_php_versions="${PVN}";
411 | }
412 | else
413 | {
414 | loc_php_versions=$(find /usr/local/php*/bin/php | sort -n | egrep -o '(5|7|8|9)[0-9]+' | xargs); #'
415 | }
416 | fi;
417 |
418 | for loc_php_version in ${loc_php_versions};
419 | do
420 | {
421 | verify_php_version "${loc_php_version}";
422 | loc_php_dotver=$(echo "${loc_php_version}" | egrep -o '(5|7|8|9)[0-9]+' | sed 's/\(.\)\(.\)/\1.\2/'); #'
423 | loc_extension_dir=$("/usr/local/php${loc_php_version}/bin/php" -i 2>&1 | grep "^extension_dir" | awk '{print $3}');
424 | loc_extension_file="${loc_extension_dir}/${EXT}.so";
425 |
426 | if [ "${EXT}" == "sourceguardian" ];
427 | then
428 | {
429 | loc_extension_file="${SOURCEGUARDIAN_DIR}/ixed.${loc_php_dotver}.lin";
430 |
431 | if [ -f "${loc_extension_file}" ];
432 | then
433 | {
434 | rm -f "${loc_extension_file}";
435 | echo "${BN}[OK] The extension ${EXT} for PHP ${loc_php_dotver} found! Removing it...${BF}";
436 | }
437 | else
438 | {
439 | echo "${BN}[Warning] The extension ${EXT} for PHP ${loc_php_dotver} not found! Nothing to disable...${BF}";
440 | }
441 | fi;
442 |
443 | do_update_ini "${loc_php_version}" "${EXT}" >/dev/null 2>&1;
444 | }
445 | else
446 | {
447 | if [ -f "${loc_extension_file}" ];
448 | then
449 | {
450 | rm -f "${loc_extension_file}";
451 | echo "${BN}[OK] The extension ${EXT} for PHP ${loc_php_dotver} found! Removing it...${BF}";
452 | }
453 | else
454 | {
455 | echo "${BN}[Warning] The extension ${EXT} for PHP ${loc_php_dotver} not found! Nothing to disable...${BF}";
456 | }
457 | fi;
458 |
459 | do_update_ini "${loc_php_version}" >/dev/null 2>&1;
460 | }
461 | fi;
462 |
463 | do_restart_webserver "${loc_php_version}";
464 | }
465 | done;
466 | }
467 |
468 | do_install_single()
469 | {
470 | local loc_php_version;
471 | loc_php_version=${1:?};
472 |
473 | if [ "${EXT}" == "sourceguardian" ];
474 | then
475 | {
476 | do_install_sourceguardian;
477 | do_update_ini "${loc_php_version}" sourceguardian;
478 | }
479 | else
480 | {
481 | find_extension_version "${loc_php_version}";
482 | do_update "${loc_php_version}";
483 | do_update_ini "${loc_php_version}";
484 | }
485 | fi;
486 | }
487 |
488 | do_install()
489 | {
490 | local loc_php_version loc_php_dotver;
491 | loc_php_version=${1};
492 |
493 | cd "${WORKDIR}";
494 |
495 | if [ -z "${loc_php_version}" ];
496 | then
497 | {
498 | while read -r PHPIZE
499 | do
500 | {
501 | loc_php_version=$(echo "${PHPIZE}" | grep -o "[0-9]*");
502 | loc_php_dotver=$(echo "${loc_php_version}" | egrep -o '(5|7|8|9)[0-9]+' | sed 's/\(.\)\(.\)/\1.\2/'); #'
503 | verify_php_version "${loc_php_version}";
504 | echo "${BN}[OK] Started with PHP ${loc_php_dotver}${BF}";
505 | do_install_single "${loc_php_version}";
506 | do_restart_webserver "${loc_php_version}";
507 | echo "${BN}[OK] Finished with PHP ${loc_php_dotver}${BF}";
508 | echo; sleep 1;
509 | }
510 | done < <(find /usr/local/php*/bin/phpize);
511 | }
512 | else
513 | {
514 | loc_php_dotver=$(echo "${loc_php_version}" | egrep -o '(5|7|8|9)[0-9]+' | sed 's/\(.\)\(.\)/\1.\2/'); #'
515 | verify_php_version "${loc_php_version}";
516 | echo "${BN}[OK] Started with PHP ${loc_php_dotver}${BF}";
517 | do_install_single "${loc_php_version}";
518 | do_restart_webserver "${loc_php_version}";
519 | echo "${BN}[OK] Finished with PHP ${loc_php_dotver}${BF}";
520 | }
521 | fi;
522 |
523 | test -d "${PWD}" && cd "${PWD}";
524 | }
525 |
526 | do_status()
527 | {
528 | local loc_php_versions loc_php_version loc_extension_dir loc_extension_file loc_php_dotver;
529 |
530 | if [ -n "${PVN}" ]; then
531 | {
532 | loc_php_versions="${PVN}";
533 | }
534 | else
535 | {
536 | loc_php_versions=$(find /usr/local/php*/bin/php | sort -n | egrep -o '(5|7|8|9)[0-9]+' | xargs); #'
537 | }
538 | fi;
539 |
540 | for loc_php_version in ${loc_php_versions};
541 | do
542 | {
543 | verify_php_version "${loc_php_version}";
544 | loc_php_dotver=$(echo "${loc_php_version}" | egrep -o '(5|7|8|9)[0-9]+' | sed 's/\(.\)\(.\)/\1.\2/'); #'
545 | loc_extension_dir=$("/usr/local/php${loc_php_version}/bin/php" -i 2>&1 | grep "^extension_dir" | awk '{print $3}');
546 | loc_extension_file="${loc_extension_dir}/${EXT}.so";
547 |
548 | if [ "${EXT}" == "sourceguardian" ];
549 | then
550 | {
551 | loc_extension_file="${SOURCEGUARDIAN_DIR}/ixed.${loc_php_dotver}.lin";
552 |
553 | if [ -f "${loc_extension_file}" ];
554 | then
555 | {
556 | echo "${BN}[OK] The extension file ${loc_extension_file} for PHP ${loc_php_dotver} found!${BF}";
557 |
558 | IS_ENABLED=$("/usr/local/php${loc_php_version}/bin/php" -m | grep -m1 -i "^${EXT}$");
559 |
560 | if [ -n "${IS_ENABLED}" ]; then
561 | {
562 | echo "${BN}[OK]${BF} The extension ${BN}${EXT}${BF} for ${BN}PHP ${loc_php_dotver}${BF} seems to be enabled!";
563 | OLD_IFS="${IFS}"; IFS=$'\n';
564 | while read -r ROW
565 | do
566 | echo "[PHP ${loc_php_dotver}] ${ROW}";
567 | done < <("/usr/local/php${loc_php_version}/bin/php" -i | grep -i "^${EXT}");
568 | IFS="${OLD_IFS}";
569 | echo "";
570 | }
571 | else
572 | {
573 | echo "${BN}[WARNING]${BF} The extension ${BN}${EXT}${BF} is probably not enabled for ${BN}PHP ${loc_php_dotver}${BF}! I did not detect it.";
574 | }
575 | fi;
576 |
577 | unset IS_ENABLED;
578 | }
579 | else
580 | {
581 | echo "${BN}[Warning] The extension file ${loc_extension_file} for PHP ${loc_php_dotver} not found${BF}";
582 | }
583 | fi;
584 | }
585 | else
586 | {
587 | if [ -f "${loc_extension_file}" ];
588 | then
589 | {
590 | IS_ENABLED=$("/usr/local/php${loc_php_version}/bin/php" -m | grep -m1 -i "^${EXT}$");
591 |
592 | if [ -n "${IS_ENABLED}" ]; then
593 | {
594 | echo "${BN}[OK]${BF} The extension ${BN}${EXT}${BF} for ${BN}PHP ${loc_php_dotver}${BF} seems to be enabled!";
595 | OLD_IFS="${IFS}"; IFS=$'\n';
596 | while read -r ROW
597 | do
598 | echo "[PHP ${loc_php_dotver}] ${ROW}";
599 | done < <("/usr/local/php${loc_php_version}/bin/php" -i | grep -i "^${EXT}");
600 | IFS="${OLD_IFS}";
601 | echo "";
602 | }
603 | else
604 | {
605 | echo "${BN}[WARNING]${BF} The extension ${BN}${EXT}${BF} is probably not enabled for ${BN}PHP ${loc_php_dotver}${BF}! I did not detect it.";
606 | }
607 | fi;
608 |
609 | unset IS_ENABLED;
610 | }
611 | else
612 | {
613 | echo "${BN}[Warning]${BF} The extension ${BN}${EXT}${BF} for ${BN}PHP ${loc_php_dotver}${BF} not found!";
614 | }
615 | fi;
616 | }
617 | fi;
618 | }
619 | done;
620 | }
621 |
622 | do_restart_webserver()
623 | {
624 | local loc_php_version loc_php_dotver loc_php_instance loc_php_mode_default loc_php_mode loc_webserver;
625 | loc_php_version=${1:?};
626 | loc_php_dotver=$(echo "${loc_php_version}" | egrep -o '(5|7|8|9)[0-9]+' | sed 's/\(.\)\(.\)/\1.\2/'); #'
627 | loc_php_instance=$(grep "^php[1-9]_release=${loc_php_dotver}" /usr/local/directadmin/custombuild/options.conf | cut -d_ -f1);
628 |
629 | if [ -n "${loc_php_instance}" ]; then
630 | {
631 | loc_php_mode_default=$(grep "^php1_mode=" /usr/local/directadmin/custombuild/options.conf | cut -d= -f2);
632 | loc_php_mode=$(grep "^${loc_php_instance}_mode=" /usr/local/directadmin/custombuild/options.conf | cut -d= -f2);
633 | loc_php_mode=${loc_php_mode:-$loc_php_mode_default};
634 |
635 | if [ "${loc_php_mode}" == "php-fpm" ]; then
636 | {
637 | echo "${BN}[INFO]${BF} Going to restart PHP-FPM ${loc_php_dotver}!";
638 | do_restart_service "php-fpm${loc_php_version}";
639 | }
640 | elif [ "${loc_php_mode}" == "lsphp" ]; then
641 | {
642 | echo "${BN}[INFO]${BF} Going to reload PHP ${loc_php_dotver} instances (${loc_php_mode})!";
643 | killall lsphp;
644 | }
645 | else
646 | {
647 | echo "${BN}[INFO]${BF} Going to restart a webserver for PHP ${loc_php_dotver} (${loc_php_mode})!";
648 | loc_webserver=$(grep ^webserver= /usr/local/directadmin/custombuild/options.conf | cut -d= -f2);
649 |
650 | case "${loc_webserver}" in
651 | nginx_apache|apache)
652 | do_restart_service "httpd";
653 | ;;
654 | openlitespeed|litespeed)
655 | do_restart_service "litespeed";
656 | ;;
657 | nginx)
658 | do_restart_service "nginx";
659 | ;;
660 | esac;
661 | }
662 | fi;
663 | }
664 | else
665 | {
666 | echo "${BN}[Warning]${BF} The PHP version ${BN}${loc_php_dotver}${BF} isn't managed by DirectAdmin!";
667 | }
668 | fi;
669 | }
670 |
671 | do_restart_service()
672 | {
673 | local loc_service;
674 | loc_service=${1:?};
675 | echo "${BN}[INFO]${BF} Restarting ${loc_service}!";
676 |
677 | if [ -e "/bin/systemctl" ]; then
678 | {
679 | /bin/systemctl restart "${loc_service}.service";
680 | }
681 | else
682 | {
683 | /sbin/service "${loc_service}" restart;
684 | }
685 | fi;
686 | }
687 |
688 | do_update_script()
689 | {
690 | local loc_temp_file;
691 | echo "${BN}[INFO]${BF} Updating the script $0 from the official repository!";
692 | echo "${BN}[INFO]${BF} HOME: https://github.com/poralix/directadmin-utils/!";
693 | loc_temp_file=$(mktemp);
694 | if [ -f "${loc_temp_file}" ];
695 | then
696 | curl -Ss "https://raw.githubusercontent.com/poralix/directadmin-utils/refs/heads/master/php/php-extension.sh" --output "${loc_temp_file}";
697 | if [ "$?" == "0" ];
698 | then
699 | cat "${loc_temp_file}" > "${SCRIPT}";
700 | chmod 750 "${SCRIPT}";
701 | echo "${BN}[INFO]${BF} Script updated OK!";
702 | rm -f "${loc_temp_file}";
703 | exit 0;
704 | else
705 | echo "${BN}[ERROR]${BF} Failed to update the script!";
706 | fi;
707 | rm -f "${loc_temp_file}";
708 | else
709 | echo "${BN}[ERROR]${BF} Failed to update the script!";
710 | fi;
711 | exit 1;
712 | }
713 |
714 | SCRIPT="${0}";
715 | CMD="${1}";
716 | EXT="${2}";
717 | PVN="";
718 | BETA="";
719 | QUIET="1";
720 | IS_CENTOS_7=$(grep -c -m1 'VERSION="7' /etc/os-release);
721 | SOURCEGUARDIAN_DIR="/usr/local/sourceguardian";
722 |
723 | [ -n "${CMD}" ] || do_usage;
724 |
725 | for ARG in "$@";
726 | do
727 | case "${ARG}" in
728 | --beta)
729 | BETA=1;
730 | ;;
731 | --php=*)
732 | PVN=$(echo "${ARG}" | cut -d= -f2 | egrep -o '^(5|7|8)[0-9]+'); #'
733 | [ -z "${PVN}" ] && do_usage;
734 | ;;
735 | --ver=*)
736 | EXT_VERSION=$(echo "${ARG}" | cut -d= -f2);
737 | [ -z "${EXT_VERSION}" ] && do_usage;
738 | ;;
739 | --verbose)
740 | QUIET=0;
741 | ;;
742 | esac;
743 | done;
744 |
745 | if [ -n "${BETA}" ] && [ -n "${EXT_VERSION}" ]; then
746 | echo "Can not use --beta and --ver= together at the same time...";
747 | exit 2;
748 | fi;
749 |
750 | case "${CMD}" in
751 | install)
752 | [ -n "${EXT}" ] || do_usage;
753 | do_install "${PVN}";
754 | ;;
755 | remove)
756 | [ -n "${EXT}" ] || do_usage;
757 | BETA=0;
758 | do_remove;
759 | ;;
760 | status)
761 | [ -n "${EXT}" ] || do_usage;
762 | BETA=0;
763 | do_status;
764 | ;;
765 | version)
766 | [ -n "${EXT}" ] || do_usage;
767 | BETA=0;
768 | do_status | grep -i 'version';
769 | ;;
770 | selfupdate)
771 | do_update_script;
772 | ;;
773 | *)
774 | BETA=0;
775 | do_usage;
776 | ;;
777 | esac;
778 |
779 | exit 0;
780 |
--------------------------------------------------------------------------------
/php/test_sockets_ssl.php:
--------------------------------------------------------------------------------
1 | [993],
12 | "smtp.gmail.com" => [25, 465, 587],
13 | ];
14 |
15 | if ($debug) {
16 | error_reporting(E_ALL);
17 | ini_set('display_errors', 1);
18 | } else {
19 | error_reporting(0);
20 | ini_set('display_errors', 0);
21 | }
22 |
23 | print "\n";
24 | foreach ($hosts as $host => $ports)
25 | {
26 | foreach ($ports as $port)
27 | {
28 | if ($test_nonssl)
29 | {
30 | print "Connection to $host:$port without SSL ";
31 | if (!($fp = fsockopen($host, $port, $errno, $errstr, 30)))
32 | {
33 | fclose($fp);
34 | print "OK";
35 | }
36 | else
37 | {
38 | print "FAILED";
39 | }
40 | print "\n";
41 | }
42 | if ($test_ssl)
43 | {
44 | print "Connection to $host:$port with SSL ";
45 | if (!($fp = fsockopen("ssl://".$host, $port, $errno, $errstr, 30)))
46 | {
47 | fclose($fp);
48 | print "OK";
49 | }
50 | else
51 | {
52 | print "FAILED";
53 | }
54 | print "\n";
55 | }
56 | }
57 | }
58 | print "
\n";
59 |
60 | exit(0);
61 |
62 |
--------------------------------------------------------------------------------
/rspamd/rspamd2-statistic-sqlite.conf:
--------------------------------------------------------------------------------
1 | # Rspamd statistic setup
2 | # Pre-built files could be loaded from:
3 | # http://rspamd.com/rspamd_statistics/bayes.spam.sqlite
4 | # - and -
5 | # http://rspamd.com/rspamd_statistics/bayes.ham.sqlite
6 |
7 | classifier "bayes" {
8 | tokenizer {
9 | name = "osb";
10 | }
11 | cache {
12 | path = "${DBDIR}/learn_cache.sqlite";
13 | }
14 | min_tokens = 11;
15 | backend = "sqlite3";
16 | languages_enabled = true;
17 | min_learns = 200;
18 |
19 | statfile {
20 | symbol = "BAYES_HAM";
21 | path = "${DBDIR}/bayes.ham.sqlite";
22 | spam = false;
23 | }
24 | statfile {
25 | symbol = "BAYES_SPAM";
26 | path = "${DBDIR}/bayes.spam.sqlite";
27 | spam = true;
28 | }
29 | learn_condition =<= 0.95
42 | else
43 | cl = 'ham'
44 | in_class = prob <= 0.05
45 | end
46 |
47 | if in_class then
48 | return false,string.format('already in class %s; probability %.2f%%',
49 | cl, math.abs((prob - 0.5) * 200.0))
50 | end
51 | end
52 | end
53 |
54 | return true
55 | end
56 | EOD
57 |
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/sftp/proftpd.conf:
--------------------------------------------------------------------------------
1 | # modified by Poralix
2 |
3 | ServerName "ProFTPd"
4 | ServerType standalone
5 |
6 | Port 0
7 | PassivePorts 35000 35999
8 | UseReverseDNS off
9 | TimesGMT off
10 | TimeoutLogin 120
11 | TimeoutIdle 600
12 | TimeoutNoTransfer 900
13 | TimeoutStalled 3600
14 |
15 | ScoreboardFile /var/run/proftpd/proftpd.pid
16 |
17 | TransferLog /var/log/proftpd/xferlog.legacy
18 | LogFormat default "%h %l %u %t \"%r\" %s %b"
19 | LogFormat auth "%v [%P] %h %t \"%r\" %s"
20 | LogFormat write "%h %l %u %t \"%r\" %s %b"
21 |
22 | #DON'T modify this log format. Its used by DirectAdmin to determine user usage
23 | LogFormat userlog "%u %b %m %a"
24 | ExtendedLog /var/log/proftpd/|SERVER_IP|.bytes WRITE,READ userlog
25 |
26 | AuthUserFile /etc/proftpd.passwd
27 | DefaultServer on
28 | AuthOrder mod_auth_file.c
29 |
30 | #AuthPAM off
31 |
32 |
33 |
34 | Port 21
35 | TLSEngine on
36 | TLSLog /var/log/proftpd/proftpd.tls.log
37 | TLSProtocol TLSv1 TLSv1.1 TLSv1.2
38 | TLSCipherSuite HIGH:MEDIUM:+TLSv1
39 | TLSVerifyClient off
40 | TLSRequired off
41 |
42 | #Certificates
43 | TLSRSACertificateFile /etc/exim.cert
44 | TLSRSACertificateKeyFile /etc/exim.key
45 | TLSCertificateChainFile /etc/exim.cacert
46 | #TLSCACertificateFile /etc/ftpd/root.cert.pem
47 |
48 | TLSCipherSuite HIGH:MEDIUM:+TLSv1:!SSLv2:+SSLv3
49 |
50 | AuthUserFile /etc/proftpd.passwd
51 | AuthOrder mod_auth_file.c
52 |
53 |
54 |
55 |
56 | PassivePorts 35000 35999
57 | DeferWelcome on
58 |
59 | RequireValidShell no
60 |
61 | DefaultRoot ~
62 | DirFakeUser on ftp
63 | DirFakeGroup on ftp
64 |
65 | User ftp
66 | Group ftp
67 | #UserAlias anonymous ftp
68 |
69 | AllowStoreRestart on
70 | AllowRetrieveRestart on
71 |
72 | #ListOptions -a
73 |
74 | Umask 022
75 | DisplayLogin welcome.msg
76 | DisplayChdir readme
77 | AllowOverwrite yes
78 | #IdentLookups off
79 | ExtendedLog /var/log/proftpd/access.log WRITE,READ write
80 | ExtendedLog /var/log/proftpd/auth.log AUTH auth
81 |
82 | #
83 | # Paranoia logging level....
84 | #
85 | #ExtendedLog /var/log/proftpd/paranoid.log ALL default
86 |
87 |
88 | Include /etc/proftpd.sftp.conf
89 |
--------------------------------------------------------------------------------
/sftp/proftpd.sftp.conf:
--------------------------------------------------------------------------------
1 | # modified by Poralix
2 |
3 |
4 |
5 | # The SFTP configuration
6 | Port 2121
7 |
8 | SFTPEngine on
9 | AuthUserFile /etc/proftpd.passwd
10 | #AuthOrder mod_auth_file.c
11 |
12 | ExtendedLog /var/log/proftpd/|SERVER_IP|.bytes WRITE,READ userlog
13 |
14 | SFTPLog /var/log/proftpd/sftp.log
15 | SFTPHostKey /etc/ssh/ssh_host_ed25519_key
16 | SFTPHostKey /etc/ssh/ssh_host_ecdsa_key
17 | SFTPHostKey /etc/ssh/ssh_host_rsa_key
18 | SFTPHostKey /etc/ssh/ssh_host_dsa_key
19 | SFTPAuthorizedUserKeys file:~/.sftp/authorized_keys
20 |
21 | MaxLoginAttempts 6
22 |
23 | SFTPClientMatch ".*WS_FTP.*" channelWindowSize 1GB #WS_FTP initial window size
24 | SFTPClientMatch ".*ClientSftp" sftpProtocolVersion 3 #CuteFTPPro8
25 | SFTPClientMatch ".*WinSCP.*" sftpProtocolVersion 3 #upload/download fix for WinSCP
26 | SFTPClientMatch ".*SecureBlackbox.*" sftpProtocolVersion 3
27 | SFTPClientMatch "1.0" sftpProtocolVersion 3 channelWindowSize 1GB
28 | SFTPClientMatch ".*J2SSH_Maverick.*" channelWindowSize 1GB
29 | SFTPClientMatch ".*WeOnlyDo.*" sftpProtocolVersion 3 channelWindowSize 1GB
30 | SFTPClientMatch ".*EldoS.SSHBlackbox.3.*" sftpProtocolVersion 3 channelWindowSize 1GB
31 | SFTPClientMatch ".*IP.Works.*" channelWindowSize 1GB
32 |
33 |
34 |
--------------------------------------------------------------------------------
/ssl/README.md:
--------------------------------------------------------------------------------
1 | # Script install_server_wide_cert.sh
2 |
3 | This script is written to be used on a directadmin powered server and can
4 | be used to do a quick installation of a SSL cert/key for server-wide usage
5 | i.e. SSL cert used by default (on hostname) in Apache/Nginx, Exim/Dovecot.
6 |
7 | # Installation
8 |
9 | ```
10 | cd /usr/local/directadmin/scripts/custom
11 | wget -O ./install_server_wide_cert.sh https://raw.githubusercontent.com/poralix/directadmin-utils/master/ssl/install_server_wide_cert.sh
12 | chmod 700 ./install_server_wide_cert.sh
13 | ```
14 |
15 | # Usage
16 |
17 | ```
18 | cd /usr/local/directadmin/scripts/custom
19 | ./install_server_wide_cert.sh []
20 | ```
21 |
22 | - PATH_TO_CERT - a full or relative path to a CERT you want to install
23 | - PATH_TO_KEY - a full or relative path to a KEY you want to install
24 | - PATH_TO_CACERT - a full or relative path to a CACERT you want to install
25 |
26 | # CACERT
27 |
28 | The cacerts file is a collection of trusted certificate authority (CA) certificates. They are Intermediate/chain certificates.
29 |
30 | # Author
31 |
32 | Alex S Grebenschikov
33 |
--------------------------------------------------------------------------------
/ssl/install_server_wide_cert.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # ============================================================================
3 | # This script is written to be used on a directadmin powered server and can
4 | # be used to do a quick installation of a SSL cert/key for server-wide usage
5 | # i.e. SSL cert used by default (on hostname) in Apache/Nginx, Exim/Dovecot.
6 | # ============================================================================
7 | # IMPORTANT: Written and tested on CentOS 6.x, 7.x only
8 | # ============================================================================
9 | # Written by: Alex S Grebenschikov (support@poralix.com)
10 | # Copyright: 2015-2022 Alex S Grebenschikov
11 | # Created at: Wed 28 Oct 2015 17:14:32 NOVT
12 | # Last modified: Mon Oct 10 18:24:44 +07 2022
13 | # Version: 0.8 $ Mon Oct 10 18:24:44 +07 2022
14 | # 0.7 $ Wed Aug 31 12:58:29 +07 2022
15 | # 0.6 $ Wed May 26 13:14:23 +07 2021
16 | # 0.5 $ Mon May 17 21:51:45 +07 2021
17 | # 0.4 $ Tue Apr 27 18:40:46 +07 2021
18 | # 0.3 $ Tue Apr 27 00:33:34 +07 2021
19 | # 0.2 $ Thu Jun 29 09:36:58 +07 2017
20 | # 0.1 $ Wed 28 Oct 2015 17:14:53 NOVT
21 | # ============================================================================
22 | #
23 |
24 | # A LIST OF SERVICES YOU WANT A CERT TO BE INSTALLED FOR
25 | SERVICES="";
26 | SERVICES="${SERVICES} directadmin";
27 | SERVICES="${SERVICES} apache";
28 | SERVICES="${SERVICES} nginx";
29 | SERVICES="${SERVICES} litespeed";
30 | SERVICES="${SERVICES} openlitespeed";
31 | SERVICES="${SERVICES} exim";
32 | SERVICES="${SERVICES} dovecot";
33 |
34 | # ============================================================================
35 | # DO NOT CHANGE ANYTHING BELLOW
36 | # ============================================================================
37 |
38 | BOLD="$(tput -Txterm bold)";
39 | RED="$(tput -Txterm setaf 1)";
40 | GREEN="$(tput -Txterm setaf 2)";
41 | RESET="$(tput -Txterm sgr0)";
42 | OPENSSL='/usr/bin/openssl';
43 |
44 | die()
45 | {
46 | echo "$1";
47 | exit $2;
48 | }
49 |
50 | do_restart()
51 | {
52 | echo;
53 | if [ -x "/bin/systemctl" ] || [ -x "/usr/bin/systemctl" ]; then
54 | echo "${GREEN}[OK]${RESET} ${BOLD}Restarting service $1${RESET}";
55 | systemctl restart $1;
56 | elif [ -x "/etc/init.d/$1" ]; then
57 | echo "${GREEN}[OK]${RESET} ${BOLD}Restarting service $1${RESET}";
58 | /etc/init.d/$1 restart;
59 | else
60 | echo "${RED}[WARNING]${RESET} You need to restart $1 manually in order to changes to take effect!";
61 | fi;
62 | }
63 |
64 | do_cert_exim_dovecot()
65 | {
66 | echo "${GREEN}[OK]${RESET} ${BOLD}Installing cert/key for Exim and Dovecot${RESET}";
67 | COMBCERTTO="/etc/exim.cert";
68 | KEYTO="/etc/exim.key";
69 | cp -v ${PCERT} ${COMBCERTTO};
70 | cp -v ${PKEY} ${KEYTO};
71 | if [ -f "${PCACERT}" ]; then
72 | echo "" >> ${COMBCERTTO};
73 | cat ${PCACERT} >> ${COMBCERTTO};
74 | fi;
75 | chmod -v 600 ${KEYTO} ${COMBCERTTO};
76 | chown -v mail ${KEYTO} ${COMBCERTTO};
77 | chgrp -v mail ${KEYTO} ${COMBCERTTO};
78 | do_restart exim;
79 | do_restart dovecot;
80 | echo;
81 | }
82 |
83 | do_cert_httpd()
84 | {
85 | CACERTTO="/etc/httpd/conf/ssl.crt/server.ca";
86 | CERTTO="/etc/httpd/conf/ssl.crt/server.crt";
87 | COMBCERTTO="/etc/httpd/conf/ssl.crt/server.crt.combined";
88 | KEYTO="/etc/httpd/conf/ssl.key/server.key";
89 | cp -v ${PCERT} ${CERTTO};
90 | cp -v ${PCERT} ${COMBCERTTO};
91 | cp -v ${PKEY} ${KEYTO};
92 | if [ -f "${PCACERT}" ]; then
93 | cp -v ${PCACERT} ${CACERTTO};
94 | echo "" >> ${COMBCERTTO};
95 | cat ${PCACERT} >> ${COMBCERTTO};
96 | fi;
97 | chmod -v 600 ${CERTTO} ${KEYTO} ${CACERTTO} ${COMBCERTTO};
98 | chown -v root ${CERTTO} ${KEYTO} ${CACERTTO} ${COMBCERTTO};
99 | chgrp -v root ${CERTTO} ${KEYTO} ${CACERTTO} ${COMBCERTTO};
100 | }
101 |
102 | do_cert_openlitespeed()
103 | {
104 | c=$(echo ${SERVICES} | grep -c "\ openlitespeed");
105 | if [ "${c}" -eq "0" ]; then
106 | echo "${RED}[WARNING]${RESET} ${BOLD}Skipping installation of cert/key for OpenLiteSpeed${RESET}";
107 | else
108 | echo "${GREEN}[OK]${RESET} ${BOLD}Installing cert/key for OpenLiteSpeed${RESET}";
109 | CACERTTO="/usr/local/lsws/ssl.crt/server.ca";
110 | CERTTO="/usr/local/lsws/ssl.crt/server.crt";
111 | COMBCERTTO="/usr/local/lsws//ssl.crt/server.crt.combined";
112 | KEYTO="/usr/local/lsws/ssl.key/server.key";
113 | cp -v ${PCERT} ${CERTTO};
114 | cp -v ${PCERT} ${COMBCERTTO};
115 | cp -v ${PKEY} ${KEYTO};
116 | if [ -f "${PCACERT}" ]; then
117 | cp -v ${PCACERT} ${CACERTTO};
118 | echo "" >> ${COMBCERTTO};
119 | cat ${PCACERT} >> ${COMBCERTTO};
120 | fi;
121 | chmod -v 600 ${CERTTO} ${KEYTO} ${CACERTTO} ${COMBCERTTO};
122 | chown -v root ${CERTTO} ${KEYTO} ${CACERTTO} ${COMBCERTTO};
123 | chgrp -v root ${CERTTO} ${KEYTO} ${CACERTTO} ${COMBCERTTO};
124 | do_cert_httpd;
125 | do_restart litespeed;
126 | fi;
127 | echo;
128 | }
129 |
130 | do_cert_litespeed()
131 | {
132 | c=$(echo ${SERVICES} | grep -c "\ litespeed");
133 | if [ "${c}" -eq "0" ]; then
134 | echo "${RED}[WARNING]${RESET} ${BOLD}Skipping installation of cert/key for Litespeed${RESET}";
135 | else
136 | echo "${GREEN}[OK]${RESET} ${BOLD}Installing cert/key for Litespeed${RESET}";
137 | do_cert_httpd;
138 | do_restart litespeed;
139 | fi;
140 | echo;
141 | }
142 |
143 | do_cert_apache()
144 | {
145 | c=$(echo ${SERVICES} | grep -c "\ apache");
146 | if [ "${c}" -eq "0" ]; then
147 | echo "${RED}[WARNING]${RESET} ${BOLD}Skipping installation of cert/key for Apache${RESET}";
148 | else
149 | echo "${GREEN}[OK]${RESET} ${BOLD}Installing cert/key for Apache${RESET}";
150 | do_cert_httpd;
151 | do_restart httpd;
152 | fi;
153 | echo;
154 | }
155 |
156 | do_cert_nginx()
157 | {
158 | c=$(echo ${SERVICES} | grep -c "\ apache");
159 | if [ "${c}" -eq "0" ]; then
160 | echo "${RED}[WARNING]${RESET} ${BOLD}Skipping installation of cert/key for NGINX${RESET}";
161 | else
162 | echo "${GREEN}[OK]${RESET} ${BOLD}Installing cert/key for NGINX${RESET}";
163 | CACERTTO="/etc/nginx/ssl.crt/server.ca";
164 | CERTTO="/etc/nginx/ssl.crt/server.crt";
165 | COMBCERTTO="/etc/nginx/ssl.crt/server.crt.combined";
166 | KEYTO="/etc/nginx/ssl.key/server.key";
167 | cp -v ${PCERT} ${CERTTO};
168 | cp -v ${PCERT} ${COMBCERTTO};
169 | cp -v ${PKEY} ${KEYTO};
170 | if [ -f "${PCACERT}" ]; then
171 | cp -v ${PCACERT} ${CACERTTO};
172 | echo "" >> ${COMBCERTTO};
173 | cat ${PCACERT} >> ${COMBCERTTO};
174 | fi;
175 | chmod -v 600 ${CERTTO} ${KEYTO} ${CACERTTO} ${COMBCERTTO};
176 | chown -v root ${CERTTO} ${KEYTO} ${CACERTTO} ${COMBCERTTO};
177 | chgrp -v root ${CERTTO} ${KEYTO} ${CACERTTO} ${COMBCERTTO};
178 | do_restart nginx;
179 | fi;
180 | echo;
181 | }
182 |
183 | do_cert_directadmin()
184 | {
185 | echo "${GREEN}[OK]${RESET} ${BOLD}Installing cert/key for Directadmin${RESET}";
186 | CERTTO="/usr/local/directadmin/conf/cacert.pem";
187 | KEYTO="/usr/local/directadmin/conf/cakey.pem";
188 | CACERTTO="";
189 | cp -v "${PCERT}" "${CERTTO}";
190 | cp -v "${PKEY}" "${KEYTO}";
191 | if [ -f "${PCACERT}" ]; then
192 | CACERTTO="/usr/local/directadmin/conf/carootcert.pem";
193 | cp -v "${PCACERT}" "${CACERTTO}";
194 | fi;
195 | chmod -v 600 ${CERTTO} ${KEYTO} ${CACERTTO};
196 | chown -v diradmin:diradmin ${CERTTO} ${KEYTO} ${CACERTTO};
197 | killall -9 directadmin;
198 | do_restart directadmin;
199 | echo;
200 | }
201 |
202 | do_cert_pureftpd()
203 | {
204 | echo "${GREEN}[OK]${RESET} ${BOLD}Installing cert/key for PureFTPd${RESET}";
205 | COMBO_CERT_TO="/etc/pure-ftpd.pem";
206 | cat ${PCERT} ${PKEY} > ${COMBO_CERT_TO};
207 | [ -f "${PCACERT}" ] && cat ${PCACERT} >> ${COMBO_CERT_TO};
208 | chmod -v 600 ${COMBO_CERT_TO};
209 | chown -v 0:0 ${COMBO_CERT_TO};
210 | do_restart pure-ftpd;
211 | echo;
212 | }
213 |
214 | do_print_copyright()
215 | {
216 | echo "==========================================================================";
217 | echo " ${BOLD}Written by Alex Grebenschikov (support@poralix.com), 2015-2022${RESET}";
218 | echo "==========================================================================";
219 | }
220 |
221 | do_print_usage()
222 | {
223 | echo "";
224 | echo "Usage: ${BOLD}${0} []${RESET}";
225 | echo "";
226 | echo " ============================================================================";
227 | echo " This script is written to be used on a directadmin powered server and can";
228 | echo " be used to do a quick installation of a SSL cert/key for server-wide usage";
229 | echo " i.e. SSL cert used by default (on hostname) in Apache/Nginx, Exim/Dovecot.";
230 | echo " ============================================================================";
231 | echo "";
232 | echo " PATH_TO_CERT - a full or relative path to a CERT you want to install";
233 | echo " PATH_TO_KEY - a full or relative path to a KEY you want to install";
234 | echo " PATH_TO_CACERT - a full or relative path to a CACERT you want to install";
235 | echo "";
236 | echo " ============================================================================";
237 | echo "";
238 | echo " Copyright (c) 2015-2022 Alex S Grebenschikov (support@poralix.com)";
239 | echo "";
240 | exit 1;
241 | }
242 |
243 | do_validate_cert()
244 | {
245 | CCERT="$1";
246 | ${OPENSSL} x509 -noout -pubkey -in ${CCERT} >/dev/null 2>&1;
247 | RES=$?;
248 | echo "[INFO] Validating CERT ${BOLD}${CCERT}${RESET}";
249 | if [ "${RES}" -gt "0" ]; then
250 | echo "${RED}[ERROR]${RESET} File ${CCERT} is not a valid CERT";
251 | exit 1;
252 | else
253 | HCERT=$(${OPENSSL} x509 -noout -pubkey -in ${CCERT} 2>&1 | ${OPENSSL} md5 | awk '{print $2}');
254 | echo "${GREEN}[OK]${RESET} The cert md5 hash: ${BOLD}${HCERT}${RESET}";
255 | fi;
256 | echo;
257 | }
258 |
259 | do_validate_key()
260 | {
261 | CKEY="$1";
262 | ${OPENSSL} pkey -pubout -in ${CKEY} >/dev/null 2>&1;
263 | RES=$?;
264 | echo "[INFO] Validating CERT ${BOLD}${CKEY}${RESET}";
265 | if [ "${RES}" -gt "0" ]; then
266 | echo "${RED}[ERROR]${RESET} File ${CKEY} is not a valid KEY";
267 | exit 1;
268 | else
269 | HKEY=$(${OPENSSL} pkey -pubout -in ${CKEY} 2>&1 | ${OPENSSL} md5 | awk '{print $2}');
270 | echo "${GREEN}[OK]${RESET} The key md5 hash: ${BOLD}${HKEY}${RESET}";
271 | fi;
272 | echo;
273 | }
274 |
275 | # PRINT USAGE
276 | [ "$#" -lt "2" ] && do_print_usage;
277 |
278 | # SET PARAMS
279 | PCERT="$1";
280 | PKEY="$2";
281 |
282 | [ -d "/usr/local/directadmin/" ] || die "${RED}[ERROR]${RESET} DirectAdmin is not installed here. Terminating..." 1;
283 | [ -f "/usr/local/directadmin/custombuild/options.conf" ] || die "${RED}[ERROR]${RESET} CustomBuild is not installed here. Terminating..." 2;
284 |
285 | do_print_copyright;
286 | do_validate_cert "${PCERT}";
287 | do_validate_key "${PKEY}";
288 |
289 | if [ "${HKEY}" == "${HCERT}" ]; then
290 | echo "${GREEN}[OK]${RESET} CERT and KEY match each other!";
291 | echo;
292 | else
293 | echo "${RED}[ERROR]${RESET} CERT and KEY do not match each other!";
294 | exit 1;
295 | fi;
296 |
297 | if [ -n "$3" ] && [ -f "$3" ]; then
298 | PCACERT="$3";
299 | echo "[INFO] You provided CACERT ${BOLD}${PCACERT}${RESET}";
300 | do_validate_cert "${PCACERT}";
301 | fi;
302 |
303 | # DIRECTADMIN
304 | c=$(echo ${SERVICES} | grep -c directadmin);
305 | [ "$c" -eq "1" ] && do_cert_directadmin;
306 |
307 | WEBSERVER=$(grep ^webserver= /usr/local/directadmin/custombuild/options.conf | awk -F= '{print $2}');
308 |
309 | case "${WEBSERVER}" in
310 | apache)
311 | # APACHE
312 | do_cert_apache;
313 | ;;
314 | nginx)
315 | # NGINX
316 | do_cert_nginx;
317 | ;;
318 | nginx_apache)
319 | # NGINX + APACHE
320 | do_cert_apache;
321 | do_cert_nginx;
322 | ;;
323 | litespeed)
324 | # LITESPEED
325 | do_cert_litespeed;
326 | ;;
327 | openlitespeed)
328 | # OPENLITESPEED
329 | do_cert_openlitespeed;
330 | ;;
331 | esac;
332 |
333 | # EXIM
334 | c=$(echo ${SERVICES} | grep -c exim);
335 | if [ "$c" -eq "1" ]; then
336 | do_cert_exim_dovecot;
337 | else
338 | c=$(echo ${SERVICES} | grep -c dovecot);
339 | [ "$c" -eq "1" ] && do_cert_exim_dovecot;
340 | fi;
341 |
342 | # PureFTPd
343 | c=$(grep -c ^ftpd=pureftpd /usr/local/directadmin/custombuild/options.conf);
344 | if [ "${c}" -eq "1" ]; then
345 | do_cert_pureftpd;
346 | fi;
347 |
348 | exit 0;
349 |
--------------------------------------------------------------------------------
/webapps/rainloop.install.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #############################################################################
3 | #
4 | # A script to install/upgrade Rainloop on Directadmin server
5 | # Written by Alex S Grebenschikov (support@poralix.com)
6 | # Version: v.0.2.1 $ Thu Aug 1 18:56:02 +07 2019
7 | #
8 | # Versions:
9 | # - v.0.2.1 $ Thu Aug 1 18:56:02 +07 2019
10 | # - v.0.2.0 $ Thu Aug 9 16:00:01 +07 2018
11 | # - v.0.1.1 $ Tue Aug 8 10:45:20 +07 2017
12 | # - v.0.1 $ Wed Jul 12 15:49:10 +07 2017
13 | #
14 | # TO DO:
15 | # - autoconfigure new installation
16 | #
17 | #############################################################################
18 | # set -x
19 |
20 | #URL="https://www.rainloop.net/repository/webmail/rainloop-community-latest.zip";
21 | #SOURCE="rainloop-community-latest.zip"
22 | URL="https://www.rainloop.net/repository/webmail/rainloop-latest.zip";
23 | SOURCE="rainloop-latest.zip"
24 | MYSQL_DB="da_rainloop";
25 | MYSQL_USER="da_rainloop";
26 | MYSQL_HOST="localhost";
27 | MYSQL_PASSWORD="";
28 | MYSQL_ACCESS_HOST="localhost";
29 |
30 | die()
31 | {
32 | echo "$1"; exit $2;
33 | }
34 |
35 | genpass()
36 | {
37 | tr -cd 'a-zA-Z0-9' < /dev/urandom 2>/dev/null | head -c${1:-`perl -le 'print int rand(7) + 10'`}
38 | }
39 |
40 | genhtaccess()
41 | {
42 | HTAF="/var/www/html/rainloop/data/.htaccess";
43 | if [ -f "${HTAF}" ]; then
44 | echo "[OK] Found ${HTAF} file. Make sure it blocks access to the data folder over HTTP/HTTPS (Apache and NGINX/Apache only)...";
45 | grep -m1 -q "^Deny from all" "${HTAF}" || echo -e "\nDeny from all" >> "${HTAF}";
46 | else
47 | echo "[OK] Creating ${HTAF} file to block access to the data folder over HTTP/HTTPS (Apache and NGINX/Apache only)...";
48 | touch "${HTAF}";
49 | chown webapps:webapps "${HTAF}";
50 | echo "Deny from all" > "${HTAF}";
51 | echo "" >> "${HTAF}";
52 | echo " Options -Indexes" >> "${HTAF}";
53 | echo "" >> "${HTAF}";
54 | fi;
55 | }
56 |
57 | MYSQL="/usr/local/bin/mysql";
58 | [ -x "${MYSQL}" ] || MYSQL="/usr/bin/mysql";
59 | [ -x "${MYSQL}" ] || die "Could not find MySQL bin! Terminating..." 1;
60 | MYSQL_OPT="--defaults-extra-file=/usr/local/directadmin/conf/my.cnf";
61 | [ -f "/usr/local/directadmin/conf/my.cnf" ] || die "Could find MySQL settings for Directadmin! Terminating..." 1;
62 |
63 | # DOWNLOAD SOURCE FILE
64 | cd /var/www/html || die "Directory /var/www/html does not exist! Terminating..." 1;
65 | wget -O "${SOURCE}" "${URL}";
66 |
67 | # UNPACK SOURCE FILE
68 | [ -s "${SOURCE}" ] || die "Download failed or file is corrupted! Terminating..." 1;
69 | [ -x "/usr/bin/unzip" ] || die "Unzip is not installed on your server! Terminating...";
70 | /usr/bin/unzip -o "${SOURCE}" -d rainloop;
71 |
72 | # GENERATE HTACCESS FILE
73 | genhtaccess;
74 |
75 | # SET CORRECT PERMISSIONS
76 | [ -d "/var/www/html/rainloop" ] || die "Rainloop failed to unpack! Terminating...";
77 | echo "[OK] Setting correct permissions on folders of RainLoop...";
78 | find /var/www/html/rainloop/ -type d -exec chmod 755 {} \;
79 | echo "[OK] Setting correct permissions on files of RainLoop...";
80 | find /var/www/html/rainloop/ -type f -exec chmod 644 {} \;
81 | echo "[OK] Settings correct owner of RainLoop files and folders...";
82 | chown -R webapps:webapps /var/www/html/rainloop/;
83 |
84 | # PROTECT DATA FOLDER
85 | echo "[OK] Protecting RainLoop data files and folders...";
86 | chmod 700 /var/www/html/rainloop/data;
87 |
88 | # UPDATE ALIASES WITH CUSTOMBUILD
89 | [ -d "/usr/local/directadmin/custombuild" ] || die "CustomBuild not found! Terminating...";
90 | [ -d "/usr/local/directadmin/custombuild/custom/" ] || mkdir "/usr/local/directadmin/custombuild/custom/"
91 | [ -f "/usr/local/directadmin/custombuild/custom/webapps.list" ] || touch "/usr/local/directadmin/custombuild/custom/webapps.list";
92 | c=$(grep -c "rainloop=rainloop" /usr/local/directadmin/custombuild/custom/webapps.list);
93 | if [ "$c" == "0" ]; then
94 | echo "[OK] Updating web-server configuration for RainLoop...";
95 | echo "rainloop=rainloop" >> /usr/local/directadmin/custombuild/custom/webapps.list;
96 | cd /usr/local/directadmin/custombuild;
97 | ./build rewrite_confs;
98 | fi;
99 |
100 | # CREATE MYSQL DB
101 | if [ ! -f "/var/www/html/rainloop/data/INSTALLED" ]; then
102 | ${MYSQL} ${MYSQL_OPT} -e "USE ${MYSQL_DB};" --host=${MYSQL_HOST} 2>/dev/null;
103 | RETVAL=$?;
104 |
105 | echo "";
106 | echo "[OK] Go to http://$(hostname)/rainloop/?admin to complete and configure installation!";
107 | echo " Default username/password for admin access:";
108 | echo " - admin";
109 | echo " - 12345";
110 |
111 | if [ "${RETVAL}" == "1" ]; then
112 | MYSQL_PASSWORD=$(genpass 16);
113 | ${MYSQL} ${MYSQL_OPT} -e "CREATE DATABASE ${MYSQL_DB};" --host=${MYSQL_HOST} 2>&1;
114 | ${MYSQL} ${MYSQL_OPT} -e "GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER,LOCK TABLES,INDEX ON ${MYSQL_DB}.* TO '${MYSQL_USER}'@'${MYSQL_ACCESS_HOST}' IDENTIFIED BY '${MYSQL_PASSWORD}';" --host=${MYSQL_HOST} 2>&1;
115 | echo "";
116 | echo "[OK] Database created: ";
117 | echo " - MySQL user: ${MYSQL_USER}";
118 | echo " - MySQL password: ${MYSQL_PASSWORD}";
119 | echo " - MySQL DB name: ${MYSQL_DB}";
120 | echo " - MySQL host: ${MYSQL_HSOT}";
121 | fi;
122 |
123 | die "[OK] Installation completed!" 0;
124 | fi;
125 |
126 | # EXIT
127 | echo "";
128 | die "[OK] Upgrade completed!" 0;
129 |
--------------------------------------------------------------------------------
/webserver-errors/400.shtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 400 Bad Request
9 |
10 |
11 | Bad Request
12 | There was an error in your request.
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
--------------------------------------------------------------------------------
/webserver-errors/401.shtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 401 Authorization Required
9 |
10 |
11 | Authorization Required
12 | This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required.
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
--------------------------------------------------------------------------------
/webserver-errors/403.shtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 403 Forbidden
9 |
10 |
11 | Forbidden
12 | You don't have permission to access on this server.
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
--------------------------------------------------------------------------------
/webserver-errors/404.shtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 404 Not Found
9 |
10 |
11 | Not Found
12 | The requested URL was not found on this server.
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
--------------------------------------------------------------------------------
/webserver-errors/500.shtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 500 Internal Server Error
9 |
10 |
11 | Internal Server Error
12 | The server encountered an internal error or misconfiguration and was unable to complete your request
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
--------------------------------------------------------------------------------
/webserver-errors/README.md:
--------------------------------------------------------------------------------
1 | # Webserver errors
2 |
3 | Files with errors adapted for modile devices:
4 |
5 | - 400.shtml - 400 Bad Request
6 | - 401.shtml - 401 Authorization Required
7 | - 403.shtml - 403 Forbidden
8 | - 404.shtml - 404 Not Found
9 | - 500.shtml - 500 Internal Server Error
10 |
11 | Default webserver errors when shown on a mobile device screen have too small fonts.
12 | It is fixed in the listed files.
13 |
--------------------------------------------------------------------------------