From 05778713e020ef7a83939581ae6532d2b9299ff9 Mon Sep 17 00:00:00 2001 From: allan Date: Fri, 19 Dec 2025 15:40:50 +0100 Subject: [PATCH] latest commit --- LICENSE | 21 ++++ README.md | 163 +++++++++++++++++++++++++ last-tested | 6 + wordpressinstall | 307 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 497 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 last-tested create mode 100755 wordpressinstall diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3eaaa81 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Allan Christensen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a31a865 --- /dev/null +++ b/README.md @@ -0,0 +1,163 @@ +# WordPress for Ubuntu 24.04 +[![OS](https://img.shields.io/badge/ubuntu-24.04-E95420)](#) +[![Shell](https://img.shields.io/badge/shell-bash-121011)](#) +[![WebServer](https://img.shields.io/badge/server-nginx-009639)](#) +[![PHP](https://img.shields.io/badge/php-fpm-777BB4)](#) +[![MariaDB](https://img.shields.io/badge/db-mariadb-003545)](#) +[![MySQL](https://img.shields.io/badge/db-mysql-4479A1)](#) +[![App](https://img.shields.io/badge/app-wordpress-21759B)](#) +[![License](https://img.shields.io/badge/License-MIT-green)](./LICENSE) + +Install WordPress on Ubuntu 24.04 server. + +This is not a demo and not an experiment. +A production-focused installer — correct permissions, prepared DB, no web-based setup guessing. + +## Why this installer exists +Most WordPress guides leave insecure permissions, unclear DB setup and missing caching. This avoids all three. + +## What this installer does +✔ Downloads the latest WordPress release +✔ Creates database + user automatically +✔ Generates validated Nginx host config +✔ Socket or password authentication supported +✔ Safe to re-run without data loss + +## What this installer does *NOT* do +It won’t stop you from running the script without reading the documentation like there’s no tomorrow. +Skip the README, and whatever happens next is your headache, not a bug report. + +--- + +## Prerequisites + +This script expects: + +✔ Nginx installed +✔ PHP-FPM installed +✔ MariaDB/MySQL running *(socket or password mode supported)* + +### Optional Installers (if you need them — saves you some googling) + +- [Install Nginx + PHP-FPM on Ubuntu](https://git.x-files.dk/webserver/nginx-ubuntu) +- [Install MariaDB on Ubuntu](https://git.x-files.dk/database/mariadb-ubuntu) +- [Install MySQL on Ubuntu](https://git.x-files.dk/database/mysql-ubuntu) + +--- + +## 1. Download + +``` +git clone https://git.x-files.dk/webapps/wordpress-ubuntu.git +``` + +``` +cd wordpress-ubuntu +``` + +--- + +## 2. Install WordPress + +``` +sudo ./wordpressinstall -n -d -u -p [options] +``` + +### Examples + +Socket authentication detected → simple command: + +``` +sudo ./wordpressinstall -n wp.example.com -d wpdb -u wpuser -p wpPass123 +``` + +Socket unavailable → add database credentials manually: + +``` +sudo ./wordpressinstall -n wp.example.com -d wpdb -u wpuser -p wpPass123 -m rootpwd +sudo ./wordpressinstall -n wp.example.com -d wpdb -u wpuser -p wpPass123 -a admin -m adminpwd +``` + +--- + +### Options + +| Flag | Meaning | +|---|---| +| `-m ` | MariaDB/MySQL admin or root password *(only if socket OFF)* | +| `-a ` | DB admin username (defaults to `root`) | +| `-h` / `--help` | Show help | + +--- + +## What this installer does + +✔ Downloads + configures latest WordPress +✔ Creates DB + DB-user if they don’t exist +✔ Generates Nginx host file automatically +✔ Detects socket vs password auth +✔ Validates Nginx (`nginx -t`) before reload +✔ Supports safe re-runs +✔ Built for production, not testing + +--- + +## After installation + +Visit: + +``` +http:///wp-admin/install.php +``` + +Complete the setup wizard — database already wired. + +--- + +## File & Config Layout + +| Path | Purpose | +|---|---| +| `/var/www/html/` | WordPress directory | +| `/etc/nginx/conf.d/.conf` | Virtualhost config | +| `/etc/nginx/conf.d/includes/wp-hardening.conf` | Security | +| `/etc/nginx/conf.d/wp-rate-limit.conf` | Rate limit | + +--- + +## HTTPS Support (443) + +Enable TLS using: + +https://git.x-files.dk/webserver/nginx-snippets/src/branch/main/hostfiles/wordpress.443.conf + +Caching snippets (disabled until uncommented): + +``` +# include /etc/nginx/nginx-snippets/cache-open-files.conf; +# include /etc/nginx/nginx-snippets/cache-statics.conf; +# include /etc/nginx/nginx-snippets/cache-js-css.conf; +``` + +--- + +## Troubleshooting + +| Issue | Cause | Fix | +|---|---|---| +| Nginx restart fails | Config error | `nginx -t` | +| DB denied | No socket auth | Use `-m` | +| PHP errors | Wrong FPM version | Check `php8.3-fpm` | + +--- + +### More Information + +More guides and documentation can be found on [wiki.x-files.dk](https://wiki.x-files.dk) + +--- + +### License +Licensed under the [MIT License](./LICENSE). + +--- diff --git a/last-tested b/last-tested new file mode 100644 index 0000000..8496aad --- /dev/null +++ b/last-tested @@ -0,0 +1,6 @@ +------------------------------------ +Last tested: 19-12-2025 (DD-MM-YYYY) +Environment: Ubuntu Server 24.04 LTS +Database : MariaDB 10.11.13 +Database : MySQL 8.0.44-0 +------------------------------------ diff --git a/wordpressinstall b/wordpressinstall new file mode 100755 index 0000000..7f1d836 --- /dev/null +++ b/wordpressinstall @@ -0,0 +1,307 @@ +#!/usr/bin/env bash + +# Author : Allan Christensen +# First Created : 22-05-2021 (DD-MM-YYYY) +# Description : Installs WordPress on Ubuntu 24.04 (MariaDB or MySQL) +# License : MIT License + +# +# Are we root +# +if [[ $(id -u) -ne 0 ]]; then echo "" && echo "Must be root or use sudo" && echo "" ; exit ; fi + +# +# Detect PHP-FPM version +# +phpfpm=$(systemctl list-unit-files --type=service | awk '/php[0-9]+\.[0-9]+-fpm\.service/ {sub(".service","",$1); print $1; exit}') +if [[ -z "$phpfpm" ]]; then printf "\nUnable to detect PHP-FPM version. Is PHP-FPM installed?\n\n" ; exit 1 ; fi + +# +# Detect database engine (MariaDB or MySQL) +# +if systemctl list-unit-files | grep -q '^mariadb\.service'; then + db_engine="mariadb" + db_service="mariadb" +elif systemctl list-unit-files | grep -q '^mysql\.service'; then + db_engine="mysql" + db_service="mysql" +else + printf "\nNo supported database server found.\n\n" + printf "You must have MariaDB or MySQL installed and enabled.\n\n" + exit 1 +fi + +# +# Check if required services are running +# +for svc in nginx "$db_service" "$phpfpm"; do + systemctl is-active --quiet "$svc" || { + printf "\n%s is not running, cannot continue...\n\n" "${svc^}" + exit 1 + } +done + +# +# Check DB authentication method +# (local root access via socket / auth_socket / passwordless) +# +if mysql -u root -e ";" 2>/dev/null; then + socketauth="yes" +else + socketauth="no" +fi + +# +# Usage +# +usage() { + printf -- "\nwordpressinstall (Ubuntu 24.04)\n\n" + printf -- "Database engine detected: %s\n\n" "$db_engine" + + if [[ "$socketauth" == "yes" ]]; then + printf -- "LOCAL ROOT ACCESS DETECTED — no need for -a or -m\n\n" + printf -- "Usage:\n" + printf -- " sudo ./wordpressinstall -n -d -u -p \n\n" + printf -- "Example:\n" + printf -- " sudo ./wordpressinstall -n wp.example.com -d wpdb -u wpuser -p wpPass123\n\n" + else + printf -- "NO LOCAL ROOT ACCESS — you must use -a and -m\n\n" + printf -- "Usage:\n" + printf -- " sudo ./wordpressinstall -n -d -u -p -a -m \n\n" + printf -- "Examples:\n" + printf -- " sudo ./wordpressinstall -n wp.example.com -d wpdb -u wpuser -p wpPass123 -a root -m RootDBPassword\n" + printf -- " sudo ./wordpressinstall -n wp.example.com -d wpdb -u wpuser -p wpPass123 -a admin -m AdminDBPassword\n\n" + fi + + printf -- "Options:\n" + printf -- " -h | -help | --help Show this help screen\n\n" +} + +# +# Let's go +# +clear + +# +# Trap: show usage if user requests help. Recognizes -help and --help as early exits before getopts +# +if [[ "$1" == "-help" || "$1" == "--help" ]]; then usage ; exit 0 ; fi + +# +# Trap: malformed or missing input. Catches empty argument or argument not starting with '-' +# +if [[ $# -eq 0 || ! $1 =~ ^- ]]; then usage ; exit 1 ; fi + +# +# Configure command line options +# +while getopts ":n:d:u:p:a:m:h" option; do + case "$option" in + n) hostname=$(echo "$OPTARG" | tr '[:upper:]' '[:lower:]');; + d) dbname="$OPTARG";; + u) dbuser="$OPTARG";; + p) dbpass="$OPTARG";; + a) db_admin_user="$OPTARG";; + m) db_admin_pwd="$OPTARG";; + h) usage; exit 0;; + :) usage; echo "" ; echo "Error! Option -$OPTARG requires an argument." ; echo "" ; exit 1;; + \?) usage; echo "" ; echo "Error! Invalid option: -$OPTARG" ; echo "" ; exit 1;; + esac +done + +# +# Parse and validate input +# +if [[ -z "$hostname" || -z "$dbname" || -z "$dbuser" || -z "$dbpass" ]]; then + usage + printf "\nERROR: Missing required arguments.\n" + printf "Hostname (-n), Database name (-d), User (-u), and Password (-p) are required.\n\n" + exit 1 +fi + +# +# Normalise DB admin defaults +# +db_admin_user="${db_admin_user:-root}" + +# +# Validate domain format (RFC-ish, same family as your other installers) +# +if [[ "$hostname" =~ ^- ]]; then + printf "\nERROR: Domain cannot start with a hyphen.\n" + printf "Example of valid input: wp.example.com\n\n" + exit 1 +fi + +if [[ "$hostname" =~ [[:space:]/_] ]]; then + printf "\nERROR: Domain cannot contain spaces, slashes, or underscores.\n\n" + exit 1 +fi + +if [[ ! "$hostname" =~ ^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$ ]]; then + printf "\nERROR: Invalid domain format.\n" + printf "Example of valid input: wp.example.com\n\n" + exit 1 +fi + +# +# Validate DB identifiers (keep it simple and safe) +# +if [[ "$dbname" =~ [^a-zA-Z0-9_] ]]; then + printf "\nERROR: Database name must only contain letters, numbers, and underscores.\n\n" + exit 1 +fi + +if [[ "$dbuser" =~ [^a-zA-Z0-9_] ]]; then + printf "\nERROR: Database user must only contain letters, numbers, and underscores.\n\n" + exit 1 +fi + +if [[ "$dbname" =~ [[:space:]] || "$dbuser" =~ [[:space:]] || "$dbpass" =~ [[:space:]] ]]; then + printf "\nERROR: Database name, user, and password cannot contain whitespace.\n\n" + exit 1 +fi + +# +# If no socket auth, require admin credentials +# +if [[ "$socketauth" == "no" ]]; then + if [[ -z "${db_admin_pwd:-}" ]]; then + usage + printf "\nERROR: No local root access detected — you must provide -a and -m.\n\n" + exit 1 + fi +fi + +# +# Ensure curl and git are installed +# +for tool in curl git; do dpkg -s "$tool" &>/dev/null || apt install -y -qq "$tool" ; done + +# +# Download, install, and configure the latest WordPress version +# +printf "\nDownloading latest WordPress package...\n" +mkdir -p /var/www/html +curl -sL https://wordpress.org/latest.tar.gz | tar -xzf - --transform "s,^wordpress,$hostname," -C "/var/www/html" || { echo "WordPress download or extraction failed"; exit 1; } + +wptarget="/var/www/html/$hostname" +cp "$wptarget/wp-config-sample.php" "$wptarget/wp-config.php" + +sed -i "s/database_name_here/$dbname/" "$wptarget/wp-config.php" +sed -i "s/username_here/$dbuser/" "$wptarget/wp-config.php" +sed -i "s/password_here/$dbpass/" "$wptarget/wp-config.php" + +# +# Adjust WordPress DB_HOST depending on DB auth type +# - socket/auth_socket prefers localhost (socket) +# - password/admin prefers 127.0.0.1 (TCP) +# +if [[ "$socketauth" == "no" ]]; then + sed -i "s/^define( 'DB_HOST'.*/define( 'DB_HOST', '127.0.0.1' );/" "$wptarget/wp-config.php" +fi + +# +# Set permissions on WordPress directory +# +chown -R www-data: "$wptarget" + +# +# Clone nginx-snippets; if nginx-snippets exists then just pull latest changes +# +nginxsnippets="/etc/nginx/nginx-snippets" +repo="https://git.x-files.dk/webserver/nginx-snippets.git" +if [[ -d "$nginxsnippets/.git" ]]; then git -C "$nginxsnippets" pull --quiet; else git clone --quiet "$repo" "$nginxsnippets"; fi + +# +# Create WordPress Nginx configuration +# +cp "$nginxsnippets/hostfiles/wordpress.80.conf" /etc/nginx/conf.d/"$hostname".conf +sed -i -- "s/DOMAIN/$hostname/g" /etc/nginx/conf.d/"$hostname".conf +sed -i "s/PHPVERSION/$phpfpm/" /etc/nginx/conf.d/"$hostname".conf + +# +# WordPress hardening +# +mkdir -p /etc/nginx/includes +cp "$nginxsnippets/wp-hardening.conf" /etc/nginx/includes/wp-hardening.conf +sed -i "s/PHPVERSION/$phpfpm/" /etc/nginx/includes/wp-hardening.conf +cp --no-clobber "$nginxsnippets/wp-rate-limit.conf" /etc/nginx/conf.d/wp-rate-limit.conf 2>/dev/null + +# +# Determine DB login method (uses earlier socketauth variable) +# +printf "\nChecking database access method...\n" + +if [[ "$socketauth" == "yes" ]]; then + dbmethod="socket" + printf "Socket authentication detected (root)\n" +else + dbmethod="admin" + printf "Using admin user authentication (%s)\n" "$db_admin_user" +fi + +# +# Create WordPress database +# +case "$dbmethod" in + socket) + mysql -u root <