latest commit

This commit is contained in:
2025-12-19 15:40:50 +01:00
commit 05778713e0
4 changed files with 497 additions and 0 deletions

21
LICENSE Normal file
View File

@@ -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.

163
README.md Normal file
View File

@@ -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 wont stop you from running the script without reading the documentation like theres 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 <domain> -d <dbname> -u <dbuser> -p <dbpass> [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 <password>` | MariaDB/MySQL admin or root password *(only if socket OFF)* |
| `-a <username>` | DB admin username (defaults to `root`) |
| `-h` / `--help` | Show help |
---
## What this installer does
✔ Downloads + configures latest WordPress
✔ Creates DB + DB-user if they dont 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://<domain>/wp-admin/install.php
```
Complete the setup wizard — database already wired.
---
## File & Config Layout
| Path | Purpose |
|---|---|
| `/var/www/html/<domain>` | WordPress directory |
| `/etc/nginx/conf.d/<domain>.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).
---

6
last-tested Normal file
View File

@@ -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
------------------------------------

307
wordpressinstall Executable file
View File

@@ -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 <domain> -d <wpdbname> -u <wpdbuser> -p <wpdbpass>\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 <domain> -d <wpdbname> -u <wpdbuser> -p <wpdbpass> -a <db-admin-user> -m <db-admin-password>\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 <<EOF
CREATE DATABASE IF NOT EXISTS $dbname;
CREATE USER IF NOT EXISTS '$dbuser'@'localhost' IDENTIFIED BY '${dbpass//\'/\'\\\'\'}';
GRANT ALL PRIVILEGES ON $dbname.* TO '$dbuser'@'localhost';
FLUSH PRIVILEGES;
EOF
;;
admin)
mysql -u "${db_admin_user}" -p"${db_admin_pwd}" <<EOF
CREATE DATABASE IF NOT EXISTS $dbname;
CREATE USER IF NOT EXISTS '$dbuser'@'localhost' IDENTIFIED BY '${dbpass//\'/\'\\\'\'}';
GRANT ALL PRIVILEGES ON $dbname.* TO '$dbuser'@'localhost';
FLUSH PRIVILEGES;
EOF
;;
esac
#
# Restarting Nginx and PHP-FPM for changes to take effect
#
printf "\nRestarting services...\n"
systemctl restart "$phpfpm"
systemctl restart nginx
#
# WordPress notice
#
wpdbhost="localhost"
[[ "$socketauth" == "no" ]] && wpdbhost="127.0.0.1"
wpnotice=$(cat <<EOF
-----------------------------------------------------------------------------------
NEXT STEP:
Go to http://$hostname/wp-admin/install.php and complete the WordPress setup
Database summary (wp-config.php):
Database Host : $wpdbhost
Database Name : $dbname
Database User : $dbuser
Database Pass : $dbpass
-----------------------------------------------------------------------------------
EOF
)
#
# Print notice
#
printf '%s\n' "$wpnotice"
#
# All done
#
printf "\nAll Done...\n"
#
# End of script
#