Initial commit.
This commit is contained in:
@@ -0,0 +1,501 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
nginxConfigFile="/etc/nginx/nginx.conf"
|
||||
nginxBackupFile="/etc/nginx/nginx.conf.configure-server.bak"
|
||||
nginxSitesAvailable="/etc/nginx/sites-available"
|
||||
nginxSitesEnabled="/etc/nginx/sites-enabled"
|
||||
nginxDefaultSite="${nginxSitesAvailable}/default.conf"
|
||||
nginxDefaultSiteLink="${nginxSitesEnabled}/default.conf"
|
||||
clacksInfoUrl="https://www.gnuterrypratchett.com/"
|
||||
nginxManagedInclude="include /etc/nginx/sites-enabled/*.conf;"
|
||||
|
||||
nginx_installed() {
|
||||
pacman -Q nginx &> /dev/null
|
||||
}
|
||||
|
||||
ufw_installed() {
|
||||
pacman -Q ufw &> /dev/null
|
||||
}
|
||||
|
||||
ensure_ufw() {
|
||||
if ufw_installed; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$(yesno "ufw is not installed. Install it now and continue?")" != "Yes" ]]; then
|
||||
msgbox "Firewall action cancelled."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! install_package ufw; then
|
||||
msgbox "Failed to install ufw."
|
||||
return 1
|
||||
fi
|
||||
|
||||
msgbox "ufw installed."
|
||||
return 0
|
||||
}
|
||||
|
||||
install_nginx() {
|
||||
local clacksHeader=""
|
||||
|
||||
if ! nginx_installed; then
|
||||
if ! install_package nginx; then
|
||||
msgbox "Failed to install nginx."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
clacksHeader="$(prompt_clacks_header || true)"
|
||||
setup_nginx_layout "$clacksHeader" || return 1
|
||||
if ! test_nginx_config; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# `sudoFlags` is initialized by the main launcher before sourcing this file.
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" systemctl enable --now nginx; then
|
||||
msgbox "nginx was configured, but the service failed to enable or start."
|
||||
return 1
|
||||
fi
|
||||
|
||||
msgbox "nginx is installed and running."
|
||||
return 0
|
||||
}
|
||||
|
||||
prompt_clacks_header() {
|
||||
local rawNames=""
|
||||
local formattedNames=()
|
||||
local nameEntry=""
|
||||
local clacksHeader=""
|
||||
|
||||
if [[ "$(yesno "Would you like to add an optional X-Clacks-Overhead header for all nginx sites?")" != "Yes" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
msgbox "X-Clacks-Overhead is a tribute header inspired by Terry Pratchett's Clacks. For more information, visit ${clacksInfoUrl}"
|
||||
rawNames="$(inputbox "Enter a comma-separated list of names for the X-Clacks-Overhead header, or leave blank to skip.")" || return 1
|
||||
if [[ -z "${rawNames//[[:space:]]/}" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
while IFS= read -r nameEntry; do
|
||||
nameEntry="${nameEntry#"${nameEntry%%[![:space:]]*}"}"
|
||||
nameEntry="${nameEntry%"${nameEntry##*[![:space:]]}"}"
|
||||
if [[ -n "$nameEntry" ]]; then
|
||||
formattedNames+=("GNU ${nameEntry}")
|
||||
fi
|
||||
done < <(printf '%s\n' "$rawNames" | tr ',' '\n')
|
||||
|
||||
if [[ "${#formattedNames[@]}" -eq 0 ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
clacksHeader="$(printf '%s, ' "${formattedNames[@]}")"
|
||||
clacksHeader="${clacksHeader%, }"
|
||||
printf '%s\n' "$clacksHeader"
|
||||
return 0
|
||||
}
|
||||
|
||||
setup_nginx_layout() {
|
||||
local clacksHeader="$1"
|
||||
local generatedConfig=""
|
||||
local tempConfig=""
|
||||
|
||||
if ! sudo "${sudoFlags[@]}" test -r "$nginxConfigFile"; then
|
||||
msgbox "Unable to read ${nginxConfigFile}. Install nginx first."
|
||||
return 1
|
||||
fi
|
||||
|
||||
generatedConfig="$(generate_nginx_config "$clacksHeader")" || {
|
||||
msgbox "Failed to generate nginx.conf."
|
||||
return 1
|
||||
}
|
||||
tempConfig="$(mktemp)"
|
||||
printf '%s\n' "$generatedConfig" > "$tempConfig"
|
||||
|
||||
# `sudoFlags` is initialized by the main launcher before sourcing this file.
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" install -d -m 755 "$nginxSitesAvailable" "$nginxSitesEnabled"; then
|
||||
rm -f "$tempConfig"
|
||||
msgbox "Failed to create the nginx site directories."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" test -e "$nginxBackupFile"; then
|
||||
# shellcheck disable=SC2154
|
||||
sudo "${sudoFlags[@]}" cp "$nginxConfigFile" "$nginxBackupFile" 2> /dev/null || true
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" install -m 644 "$tempConfig" "$nginxConfigFile"; then
|
||||
rm -f "$tempConfig"
|
||||
msgbox "Failed to write ${nginxConfigFile}."
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm -f "$tempConfig"
|
||||
ensure_default_site
|
||||
}
|
||||
|
||||
generate_nginx_config() {
|
||||
local clacksHeader="$1"
|
||||
|
||||
sudo "${sudoFlags[@]}" awk -v clacksHeader="$clacksHeader" -v managedInclude="$nginxManagedInclude" '
|
||||
BEGIN {
|
||||
skippingServer = 0
|
||||
braceDepth = 0
|
||||
insertedSitesInclude = 0
|
||||
skipManagedComment = 0
|
||||
}
|
||||
{
|
||||
if ($0 == "# Managed by configure-server") {
|
||||
skipManagedComment = 1
|
||||
next
|
||||
}
|
||||
|
||||
if ($0 ~ /^[[:space:]]*add_header X-Clacks-Overhead /) {
|
||||
next
|
||||
}
|
||||
|
||||
if ($0 ~ /^[[:space:]]*include \/etc\/nginx\/sites-enabled\/\*\.conf;$/) {
|
||||
next
|
||||
}
|
||||
|
||||
if (skippingServer) {
|
||||
opens = gsub(/\{/, "{")
|
||||
closes = gsub(/\}/, "}")
|
||||
braceDepth += opens - closes
|
||||
if (braceDepth <= 0) {
|
||||
skippingServer = 0
|
||||
}
|
||||
next
|
||||
}
|
||||
|
||||
if ($0 ~ /^ server \{$/) {
|
||||
skippingServer = 1
|
||||
braceDepth = 1
|
||||
next
|
||||
}
|
||||
|
||||
if (skipManagedComment) {
|
||||
skipManagedComment = 0
|
||||
}
|
||||
|
||||
print
|
||||
|
||||
if (!insertedSitesInclude && $0 ~ /^[[:space:]]*#gzip[[:space:]]+on;/) {
|
||||
if (clacksHeader != "") {
|
||||
print ""
|
||||
print " add_header X-Clacks-Overhead \"" clacksHeader "\" always;"
|
||||
}
|
||||
print ""
|
||||
print " " managedInclude
|
||||
insertedSitesInclude = 1
|
||||
}
|
||||
}
|
||||
' "$nginxConfigFile"
|
||||
}
|
||||
|
||||
ensure_default_site() {
|
||||
local tempSiteFile=""
|
||||
|
||||
if [[ -e "$nginxDefaultSite" ]]; then
|
||||
if [[ ! -L "$nginxDefaultSiteLink" ]]; then
|
||||
# `sudoFlags` is initialized by the main launcher before sourcing this file.
|
||||
# shellcheck disable=SC2154
|
||||
sudo "${sudoFlags[@]}" ln -sf "$nginxDefaultSite" "$nginxDefaultSiteLink"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
tempSiteFile="$(mktemp)"
|
||||
cat > "$tempSiteFile" <<'EOF'
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# `sudoFlags` is initialized by the main launcher before sourcing this file.
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" install -m 644 "$tempSiteFile" "$nginxDefaultSite"; then
|
||||
rm -f "$tempSiteFile"
|
||||
msgbox "Failed to create the default nginx site."
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm -f "$tempSiteFile"
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" ln -sf "$nginxDefaultSite" "$nginxDefaultSiteLink"; then
|
||||
msgbox "Failed to enable the default nginx site."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
create_site() {
|
||||
local siteName=""
|
||||
local serverNames=""
|
||||
local siteRoot=""
|
||||
local tempSiteFile=""
|
||||
local siteConfigFile=""
|
||||
local defaultIndexFile=""
|
||||
|
||||
if ! nginx_installed; then
|
||||
msgbox "Install nginx first."
|
||||
return 1
|
||||
fi
|
||||
|
||||
siteName="$(inputbox "Enter a short site name for the config file, for example example.com.")" || return 1
|
||||
if [[ -z "$siteName" || ! "$siteName" =~ ^[A-Za-z0-9._-]+$ ]]; then
|
||||
msgbox "Enter a valid site name using letters, numbers, dots, dashes, or underscores."
|
||||
return 1
|
||||
fi
|
||||
|
||||
serverNames="$(inputbox "Enter the server_name value, using spaces between names." "$siteName")" || return 1
|
||||
siteRoot="$(inputbox "Enter the site document root." "/srv/http/${siteName}")" || return 1
|
||||
if [[ -z "$siteRoot" ]]; then
|
||||
msgbox "A document root is required."
|
||||
return 1
|
||||
fi
|
||||
|
||||
siteConfigFile="${nginxSitesAvailable}/${siteName}.conf"
|
||||
tempSiteFile="$(mktemp)"
|
||||
cat > "$tempSiteFile" <<EOF
|
||||
server {
|
||||
listen 80;
|
||||
server_name ${serverNames};
|
||||
|
||||
root ${siteRoot};
|
||||
index index.html index.htm;
|
||||
|
||||
location / {
|
||||
try_files \$uri \$uri/ =404;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# `sudoFlags` is initialized by the main launcher before sourcing this file.
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" install -d -m 755 "$siteRoot"; then
|
||||
rm -f "$tempSiteFile"
|
||||
msgbox "Failed to create ${siteRoot}."
|
||||
return 1
|
||||
fi
|
||||
|
||||
defaultIndexFile="$(mktemp)"
|
||||
cat > "$defaultIndexFile" <<EOF
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>${siteName}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>${siteName}</h1>
|
||||
<p>nginx is serving ${siteName} from ${siteRoot}.</p>
|
||||
</body>
|
||||
</html>
|
||||
EOF
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" install -m 644 "$tempSiteFile" "$siteConfigFile"; then
|
||||
rm -f "$tempSiteFile" "$defaultIndexFile"
|
||||
msgbox "Failed to write ${siteConfigFile}."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" test -e "${siteRoot}/index.html"; then
|
||||
# shellcheck disable=SC2154
|
||||
sudo "${sudoFlags[@]}" install -m 644 "$defaultIndexFile" "${siteRoot}/index.html" || true
|
||||
fi
|
||||
|
||||
rm -f "$tempSiteFile" "$defaultIndexFile"
|
||||
msgbox "Site ${siteName} was created in ${nginxSitesAvailable}. Enable it from the nginx menu when you are ready."
|
||||
return 0
|
||||
}
|
||||
|
||||
select_site_file() {
|
||||
local searchPath="$1"
|
||||
local filePattern="$2"
|
||||
local selectedSite=""
|
||||
local siteEntries=()
|
||||
local sitePath=""
|
||||
|
||||
while IFS= read -r sitePath; do
|
||||
[[ -n "$sitePath" ]] && siteEntries+=("$(basename "$sitePath")")
|
||||
done < <(find "$searchPath" -maxdepth 1 -type "$filePattern" -name '*.conf' | sort)
|
||||
|
||||
if [[ "${#siteEntries[@]}" -eq 0 ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
selectedSite="$(menulist "${siteEntries[@]}")" || return 1
|
||||
printf '%s\n' "$selectedSite"
|
||||
}
|
||||
|
||||
enable_site() {
|
||||
local siteName=""
|
||||
|
||||
if ! nginx_installed; then
|
||||
msgbox "Install nginx first."
|
||||
return 1
|
||||
fi
|
||||
|
||||
siteName="$(select_site_file "$nginxSitesAvailable" f)" || {
|
||||
msgbox "No available site configs were found."
|
||||
return 1
|
||||
}
|
||||
|
||||
# `sudoFlags` is initialized by the main launcher before sourcing this file.
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" ln -sf "${nginxSitesAvailable}/${siteName}" "${nginxSitesEnabled}/${siteName}"; then
|
||||
msgbox "Failed to enable ${siteName}."
|
||||
return 1
|
||||
fi
|
||||
|
||||
msgbox "${siteName} is enabled. Test and reload nginx when you are ready."
|
||||
return 0
|
||||
}
|
||||
|
||||
disable_site() {
|
||||
local siteName=""
|
||||
|
||||
if ! nginx_installed; then
|
||||
msgbox "Install nginx first."
|
||||
return 1
|
||||
fi
|
||||
|
||||
siteName="$(select_site_file "$nginxSitesEnabled" l)" || {
|
||||
msgbox "No enabled sites were found."
|
||||
return 1
|
||||
}
|
||||
|
||||
# `sudoFlags` is initialized by the main launcher before sourcing this file.
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" rm -f "${nginxSitesEnabled}/${siteName}"; then
|
||||
msgbox "Failed to disable ${siteName}."
|
||||
return 1
|
||||
fi
|
||||
|
||||
msgbox "${siteName} is disabled. Test and reload nginx when you are ready."
|
||||
return 0
|
||||
}
|
||||
|
||||
test_nginx_config() {
|
||||
local tempFile=""
|
||||
local status=0
|
||||
local statusText=""
|
||||
|
||||
if ! nginx_installed; then
|
||||
msgbox "Install nginx first."
|
||||
return 1
|
||||
fi
|
||||
|
||||
tempFile="$(mktemp)"
|
||||
# `sudoFlags` is initialized by the main launcher before sourcing this file.
|
||||
# shellcheck disable=SC2154
|
||||
statusText="$(sudo "${sudoFlags[@]}" nginx -t 2>&1)"
|
||||
status=$?
|
||||
printf '%s\n' "$statusText" > "$tempFile"
|
||||
textbox "$tempFile"
|
||||
rm -f "$tempFile"
|
||||
return "$status"
|
||||
}
|
||||
|
||||
reload_nginx() {
|
||||
if ! nginx_installed; then
|
||||
msgbox "Install nginx first."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! test_nginx_config; then
|
||||
msgbox "nginx was not reloaded because the config test failed."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# `sudoFlags` is initialized by the main launcher before sourcing this file.
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" systemctl reload nginx; then
|
||||
msgbox "Failed to reload nginx."
|
||||
return 1
|
||||
fi
|
||||
|
||||
msgbox "nginx reloaded successfully."
|
||||
return 0
|
||||
}
|
||||
|
||||
open_web_ports() {
|
||||
ensure_ufw || return 1
|
||||
|
||||
# `sudoFlags` is initialized by the main launcher before sourcing this file.
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" ufw allow 80/tcp; then
|
||||
msgbox "Failed to open 80/tcp."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
if ! sudo "${sudoFlags[@]}" ufw allow 443/tcp; then
|
||||
msgbox "Failed to open 443/tcp."
|
||||
return 1
|
||||
fi
|
||||
|
||||
msgbox "Web ports 80/tcp and 443/tcp are allowed."
|
||||
return 0
|
||||
}
|
||||
|
||||
while true; do
|
||||
nginxChoice="$(menulist \
|
||||
"Install nginx" \
|
||||
"Create site" \
|
||||
"Enable site" \
|
||||
"Disable site" \
|
||||
"Test config" \
|
||||
"Reload nginx" \
|
||||
"Open web ports" \
|
||||
"Back")" || break
|
||||
|
||||
case "$nginxChoice" in
|
||||
"Install nginx")
|
||||
install_nginx
|
||||
;;
|
||||
"Create site")
|
||||
create_site
|
||||
;;
|
||||
"Enable site")
|
||||
enable_site
|
||||
;;
|
||||
"Disable site")
|
||||
disable_site
|
||||
;;
|
||||
"Test config")
|
||||
test_nginx_config
|
||||
;;
|
||||
"Reload nginx")
|
||||
reload_nginx
|
||||
;;
|
||||
"Open web ports")
|
||||
open_web_ports
|
||||
;;
|
||||
"Back")
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
Reference in New Issue
Block a user