WordPress

Установка WordPress на Ubuntu 24.04: готовый скрипт с темой Hostfera

Скрипт устанавливает Nginx, PHP, MariaDB, WordPress и выбранную тему Journal или Community. Полный исходник, проверка SHA-256, доступ через SSH и следующие шаги.

Установка WordPress на Ubuntu 24.04: готовый скрипт с темой Hostfera

Этот скрипт устанавливает WordPress на Ubuntu 24.04 LTS: Nginx, PHP 8.3, MariaDB, отдельную базу и одну из бесплатных тем Hostfera. Можно выбрать Journal для блога или Community для небольшого сообщества. После установки останутся домен, HTTPS и наполнение сайта.

Какой результат вы получите

Новый сайт создаётся отдельно от других проектов: со своим каталогом, системным пользователем, базой и пулом PHP-FPM. Существующие каталоги и настройки сайтов скрипт не заменяет. Повторный запуск с занятым именем останавливается.

Первоначальный адрес — http://127.0.0.1:18080. Он доступен с вашего компьютера через зашифрованный SSH-туннель. Скрипт не открывает этот порт всему интернету: так можно настроить WordPress до готовности домена и сертификата. Поисковая индексация и публичная регистрация изначально выключены.

Скрипт устанавливает нужные пакеты и запускает системные службы. Для первого самостоятельного сайта используйте отдельный VPS. Сервер с Apache, другая ОС и нестандартная настройка базы требуют отдельной инструкции. На общем виртуальном хостинге используйте установщик провайдера.

Что подготовить

  • VPS с Ubuntu 24.04 LTS и доступом root либо sudo.
  • Рабочую почту администратора.
  • Доступ к репозиториям Ubuntu, wordpress.org, GitHub и hostfera.ru по HTTPS.
  • Свободный локальный порт и не менее 2 ГБ свободного диска для установки.

Объём памяти выбирайте под проект; разумно начать оценку с 2 ГБ для небольшого сайта и затем измерять использование ресурсов. Это ориентир для старта, а не обещание определённой посещаемости. Помочь с конфигурацией может Hostfera Select.

Если вы ещё не заходили на VPS, сначала пройдите подключение по SSH. Установщик не меняет правила межсетевого экрана. Для будущего публичного сайта понадобятся TCP 80 и 443, а SSH-доступ должен сохраняться; это разобрано в инструкции по UFW.

Скачайте и проверьте установщик

Скачать install-wordpress-1.0.0.sh.

Выполните на VPS:

curl --fail --show-error --location --proto '=https' \
  https://hostfera.ru/static/downloads/install-wordpress-1.0.0.sh \
  -o install-wordpress-1.0.0.sh
printf '%s  %s\n' '5a25e5ee52ff7e587068c1dec3e453aea9bfd5d5e896a583c7bc49185a5d9a14' \
  install-wordpress-1.0.0.sh | sha256sum --check
bash -n install-wordpress-1.0.0.sh
less install-wordpress-1.0.0.sh

Ожидаемый результат проверки SHA-256 — OK. Ознакомьтесь с кодом перед запуском: он работает с правами администратора. Скачивание и выполнение здесь разделены, чтобы можно было проверить файл.

Запустите установку с выбранной темой

Замените почту и название на свои:

sudo bash install-wordpress-1.0.0.sh \
  --site myblog \
  --theme journal \
  --port 18080 \
  --email your.name@example.com \
  --title 'Мой первый сайт' \
  --admin siteowner

--site — техническое имя из 3–12 строчных латинских букв и цифр, первая — буква. Оно используется в путях и именах ресурсов; это не домен. --port — свободный порт от 10000 до 60000. Пароль администратора создаётся случайно.

Для Community до первого запуска замените --theme journal на --theme community. Остальные параметры относятся к самому сайту. Если уже установленную тему нужно поменять, загрузите другой ZIP из панели WordPress; запускать установщик заново для этого не нужно.

Скрипт проверяет SHA-256 архивов тем и WP-CLI. Ядро загружается официальным русским ZIP и проверяется по контрольным суммам WordPress. Установка из ZIP обходит обнаруженную при проверке проблему распаковки длинных путей через WP-CLI.

Откройте WordPress через SSH-туннель

На своём компьютере откройте отдельный терминал:

ssh -N -L 18080:127.0.0.1:18080 SSH_USER@SERVER_IP

Замените SSH_USER и SERVER_IP на пользователя SSH и адрес VPS. Оставьте терминал открытым и перейдите в браузере по http://127.0.0.1:18080/, затем по http://127.0.0.1:18080/wp-admin/.

Если локальный порт занят на вашем компьютере, освободите его либо изначально выберите другой порт установки и используйте его в обеих частях туннеля. WordPress уже хранит свой полный адрес, поэтому простая замена только левого порта может приводить к перенаправлению на прежний адрес.

Данные входа прочитайте на VPS:

sudo cat /root/hostfera-myblog.credentials

Файл доступен только root. В нём находятся локальный URL, логин, сгенерированный пароль и почта. Сохраните пароль у себя. Скрипт не отправляет уведомление об установке и не настраивает доставку почты WordPress — её нужно проверить отдельно.

Что установлено на сервере

Для примера myblog создаются:

Ресурс Значение
Каталог WordPress /var/www/hostfera-myblog
Пользователь и база hfwp_myblog
PHP-пул /etc/php/8.3/fpm/pool.d/hostfera-myblog.conf
PHP-сокет /run/php/hostfera-myblog.sock
Локальный виртуальный хост /etc/nginx/sites-available/hostfera-myblog
Данные входа /root/hostfera-myblog.credentials

У темы нет демонстрационных материалов из презентации. Вы получите чистую установку с выбранным оформлением и штатным стартовым содержимым WordPress. В Community дополнительно создаются её служебные страницы.

Если установка остановилась

Прочитайте последнюю ошибку. Не запускайте тот же процесс повторно с новым именем ради обхода причины: это может создать несколько ненужных баз и каталогов.

Скрипт не удаляет созданные данные при ошибке. Это позволяет разобраться с состоянием и сохранить возможные результаты. Если сбой произошёл после создания пользователя или базы, повторный запуск с тем же именем остановится. Исправляйте конкретный шаг либо удаляйте только ресурсы этой новой тестовой установки после их проверки.

Ошибка загрузки требует проверки сети и URL. Несовпадение SHA-256 — повод остановиться и сверить версию пакета. Ошибка nginx -t или php-fpm8.3 -t требует проверки указанной конфигурации до перезагрузки службы.

Проверка установки

Установщик 1.0.0 проверен 29 октября 2026 года на Ubuntu 24.04.5 LTS с PHP 8.3 и MariaDB 10.11: отдельно установлены WordPress 7.1.4 с Journal 1.1.1 и с Community 1.0.1. Это были новые изолированные сайты на хосте с уже работающим Nginx и WordPress; первичная установка пакетов на полностью пустой ОС отдельно не проверялась.

Проверены контрольные суммы ядра, активация тем, ответы страниц и ресурсов, ограничения доступа к конфигурации и PHP в загрузках. Повторный запуск не перезаписал установленный сайт. Действовавшее демо сохранило тему, записи и конфигурацию. Такая проверка не заменяет испытание всех плагинов или будущей нагрузки вашего проекта.

Результат установки WordPress с темой Hostfera Journal через проверенный скрипт
Новая установка WordPress с Journal: штатная первая запись
Результат установки WordPress с темой Hostfera Community через проверенный скрипт
Новая установка WordPress с Community: начальная лента

Полный исходный код установщика

Ниже тот же код, что находится в скачиваемом файле версии 1.0.0:

#!/usr/bin/env bash
# Hostfera WordPress installer 1.0.0. Ubuntu 24.04 LTS, Nginx, PHP 8.3, MariaDB.
# Installs a NEW isolated site on a loopback port; never replaces an existing site.
set -Eeuo pipefail
umask 077
export LC_ALL=C.UTF-8 DEBIAN_FRONTEND=noninteractive
die() { printf '%s\n' "Ошибка: $*" >&2; exit 1; }
trap 'printf "Установка остановлена на строке %s. Не запускайте повторно с тем же именем: сначала проверьте созданные ресурсы.\n" "$LINENO" >&2' ERR
[[ $EUID -eq 0 ]] || die 'Запустите через sudo bash.'
set +x
[[ -r /etc/os-release ]] || die 'Не определена ОС.'
. /etc/os-release
[[ $ID == ubuntu && $VERSION_ID == 24.04 ]] || die 'Поддерживается Ubuntu 24.04 LTS.'

SITE='' THEME='' PORT='' EMAIL='' TITLE='Мой сайт' ADMIN='siteowner'
while (($#)); do
  [[ $# -ge 2 ]] || die 'Ожидаются пары --параметр значение.'
  case "$1" in
    --site) SITE=$2;; --theme) THEME=$2;; --port) PORT=$2;;
    --email) EMAIL=$2;; --title) TITLE=$2;; --admin) ADMIN=$2;;
    *) die "Неизвестный параметр: $1";;
  esac
  shift 2
done
[[ $SITE =~ ^[a-z][a-z0-9]{2,11}$ ]] || die '--site: от 3 до 12 строчных латинских букв и цифр; первая буква.'
[[ $PORT =~ ^[0-9]{5}$ && $PORT -ge 10000 && $PORT -le 60000 ]] || die '--port: число от 10000 до 60000.'
[[ $EMAIL =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]] || die '--email: укажите свою рабочую почту.'
[[ $ADMIN =~ ^[a-zA-Z][a-zA-Z0-9_-]{2,30}$ ]] || die '--admin: логин от 3 до 31 символа.'
[[ -n $TITLE && ${#TITLE} -le 120 ]] || die '--title: от 1 до 120 символов.'
if systemctl is-active --quiet apache2; then die 'На сервере работает Apache. Используйте отдельный VPS с Nginx.'; fi
case "$THEME" in
  journal)
    THEME_SLUG=hostfera-journal
    ARCHIVE=hostfera-journal-1.1.1.zip
    THEME_SHA=25e2c743ced48d89a544cf759ea71f1f7ace612e42779f8545693b1459ae406f;;
  community)
    THEME_SLUG=hostfera-community
    ARCHIVE=hostfera-community-1.0.1.zip
    THEME_SHA=335a8182d6699fcabb21a2cf9f6b1f7c7766301057596fd2f56ae69539600bab;;
  *) die '--theme: journal или community.';;
esac
ACCOUNT=hfwp_$SITE
WEBROOT=/var/www/hostfera-$SITE
DB=$ACCOUNT
POOL=/etc/php/8.3/fpm/pool.d/hostfera-$SITE.conf
VHOST=/etc/nginx/sites-available/hostfera-$SITE
ENABLED=/etc/nginx/sites-enabled/hostfera-$SITE
SOCKET=/run/php/hostfera-$SITE.sock
CREDENTIALS=/root/hostfera-$SITE.credentials
WPCLI=/usr/local/lib/hostfera/wp-cli-2.12.0.phar
WPCLI_SHA=ce34ddd838f7351d6759068d09793f26755463b4a4610a5a5c0a97b68220d85c
URL=http://127.0.0.1:$PORT

for target in "$WEBROOT" "$POOL" "$VHOST" "$ENABLED" "$CREDENTIALS"; do
  [[ ! -e $target && ! -L $target ]] || die "Уже существует: $target"
done
! getent passwd "$ACCOUNT" >/dev/null || die 'Системный пользователь уже существует.'
! getent group "$ACCOUNT" >/dev/null || die 'Системная группа уже существует.'
! ss -H -ltn "sport = :$PORT" | grep -q . || die 'Порт уже занят.'
[[ $(df -Pm /var | awk 'NR==2 {print $4}') -ge 2048 ]] || die 'Нужно не менее 2 ГБ свободного места.'
command -v flock >/dev/null || die 'Требуется flock из util-linux.'
exec 9>/run/lock/hostfera-wordpress-installer.lock
flock -n 9 || die 'Другой установщик уже работает.'

printf 'Установка пакетов. Существующие сайты и виртуальные хосты сохраняются.\n'
apt-get update -qq
apt-get install -y --no-upgrade nginx mariadb-server php8.3-fpm php8.3-cli \
  php8.3-mysql php8.3-xml php8.3-mbstring php8.3-curl php8.3-zip php8.3-gd \
  php8.3-intl curl ca-certificates unzip openssl
systemctl enable --now mariadb php8.3-fpm nginx
[[ $(mariadb --batch --skip-column-names -e "SELECT COUNT(*) FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='$DB'") == 0 ]] || die 'База уже существует.'
[[ $(mariadb --batch --skip-column-names -e "SELECT COUNT(*) FROM mysql.user WHERE User='$DB'") == 0 ]] || die 'Пользователь базы уже существует.'

TEMP=$(mktemp -d /tmp/hostfera-wp.XXXXXXXX)
trap 'rm -rf -- "$TEMP"' EXIT
fetch() { curl --fail --silent --show-error --location --proto '=https' --proto-redir '=https' --tlsv1.2 --connect-timeout 20 --max-time 300 "$1" -o "$2"; }
fetch "https://hostfera.ru/static/downloads/$ARCHIVE" "$TEMP/theme.zip"
printf '%s  %s\n' "$THEME_SHA" "$TEMP/theme.zip" | sha256sum --check --status || die 'Не совпала SHA-256 темы.'
fetch 'https://ru.wordpress.org/latest-ru_RU.zip' "$TEMP/wordpress.zip"
unzip -tq "$TEMP/wordpress.zip" >/dev/null
unzip -q "$TEMP/wordpress.zip" -d "$TEMP/core"
[[ -f $TEMP/core/wordpress/wp-includes/version.php ]] || die 'Не найдено ядро в официальном ZIP.'
if [[ ! -f $WPCLI ]]; then
  fetch 'https://github.com/wp-cli/wp-cli/releases/download/v2.12.0/wp-cli-2.12.0.phar' "$TEMP/wp.phar"
  printf '%s  %s\n' "$WPCLI_SHA" "$TEMP/wp.phar" | sha256sum --check --status || die 'Не совпала SHA-256 WP-CLI.'
  install -D -m 0755 "$TEMP/wp.phar" "$WPCLI"
fi
printf '%s  %s\n' "$WPCLI_SHA" "$WPCLI" | sha256sum --check --status || die 'Установленная WP-CLI отличается от проверенной версии.'
chmod 0755 /usr/local/lib/hostfera

useradd --system --user-group --home-dir "$WEBROOT" --shell /usr/sbin/nologin "$ACCOUNT"
install -d -m 0755 -o "$ACCOUNT" -g "$ACCOUNT" "$WEBROOT"
cp -a "$TEMP/core/wordpress/." "$WEBROOT/"
chown -R "$ACCOUNT:$ACCOUNT" "$WEBROOT"
install -m 0644 "$TEMP/theme.zip" "$WEBROOT/.hostfera-theme.zip"
DB_PASSWORD=$(openssl rand -hex 24)
ADMIN_PASSWORD=$(openssl rand -hex 20)
printf 'URL=%s\nLOGIN=%s\nPASSWORD=%s\nEMAIL=%s\nTHEME=%s\n' \
  "$URL" "$ADMIN" "$ADMIN_PASSWORD" "$EMAIL" "$THEME_SLUG" > "$CREDENTIALS"
chmod 0600 "$CREDENTIALS"
mariadb <<SQL
CREATE DATABASE \`$DB\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER '$DB'@'localhost' IDENTIFIED BY '$DB_PASSWORD';
GRANT ALL PRIVILEGES ON \`$DB\`.* TO '$DB'@'localhost';
SQL
wp_site() { (cd "$WEBROOT" && runuser -u "$ACCOUNT" -- env WP_CLI_CACHE_DIR="$WEBROOT/.wp-cli/cache" php "$WPCLI" --path="$WEBROOT" "$@"); }
wp_site core verify-checksums --locale=ru_RU
printf '%s\n' "$DB_PASSWORD" | wp_site config create --dbname="$DB" --dbuser="$DB" --dbhost=localhost --prompt=dbpass --quiet
chmod 0600 "$WEBROOT/wp-config.php"
unset DB_PASSWORD
wp_site config set DISALLOW_FILE_EDIT true --raw
wp_site config set WP_ENVIRONMENT_TYPE staging
printf '%s\n' "$ADMIN_PASSWORD" | wp_site core install --url="$URL" --title="$TITLE" \
  --admin_user="$ADMIN" --admin_email="$EMAIL" --prompt=admin_password --skip-email
unset ADMIN_PASSWORD
wp_site option update blog_public 0
wp_site option update users_can_register 0
wp_site option update default_role subscriber
wp_site option update timezone_string Europe/Moscow
wp_site option update comment_moderation 1
wp_site option update show_on_front posts
wp_site rewrite structure '/%postname%/'
wp_site theme install "$WEBROOT/.hostfera-theme.zip" --activate
if [[ $THEME == community ]]; then
  wp_site eval 'hfc_install_data(); hfc_setup_pages();'
fi
rm -- "$WEBROOT/.hostfera-theme.zip"
find "$WEBROOT" -type d -exec chmod 0755 {} +
find "$WEBROOT" -type f ! -name wp-config.php -exec chmod 0644 {} +
chmod 0600 "$WEBROOT/wp-config.php"

cat > "$POOL" <<CONF
[$ACCOUNT]
user = $ACCOUNT
group = $ACCOUNT
listen = $SOCKET
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 3
pm.process_idle_timeout = 10s
pm.max_requests = 300
php_admin_value[memory_limit] = 192M
php_admin_value[upload_max_filesize] = 32M
php_admin_value[post_max_size] = 40M
php_admin_flag[display_errors] = off
security.limit_extensions = .php
CONF
chmod 0644 "$POOL"
cat > "$VHOST" <<NGINX
server {
    listen 127.0.0.1:$PORT;
    server_name _;
    root $WEBROOT;
    index index.php;
    client_max_body_size 40m;
    add_header X-Content-Type-Options nosniff always;
    add_header X-Robots-Tag "noindex, nofollow" always;
    location / { try_files \$uri \$uri/ /index.php?\$args; }
    location = /xmlrpc.php { deny all; }
    location = /wp-config.php { deny all; }
    location ~ /\. { deny all; }
    location ~* ^/wp-content/uploads/.*\.(?:php[0-9]?|phtml|phar)(?:/|$) { deny all; }
    location ~* \.(?:sql|log|bak|ini|conf)$ { deny all; }
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:$SOCKET;
        fastcgi_hide_header X-Powered-By;
    }
}
NGINX
chmod 0644 "$VHOST"
ln -s "$VHOST" "$ENABLED"
php-fpm8.3 -t
nginx -t
systemctl reload php8.3-fpm
systemctl reload nginx
wp_site core is-installed
[[ $(wp_site option get stylesheet) == "$THEME_SLUG" ]] || die 'Тема не активна.'
curl --fail --silent --show-error --max-time 30 "$URL/" -o /dev/null
printf '\nWordPress установлен: %s\nТема: %s\nДанные входа: %s (доступ только root)\n' "$URL" "$THEME_SLUG" "$CREDENTIALS"
printf 'Откройте SSH-туннель с вашего компьютера: ssh -N -L %s:127.0.0.1:%s SSH_USER@SERVER_IP\n' "$PORT" "$PORT"
printf 'Затем откройте %s/wp-admin/ . До подключения домена и HTTPS сайт доступен только через туннель.\n' "$URL"
printf 'Инструкция: https://hostfera.ru/blog/domen-i-https-dlya-wordpress-na-vps/\n'

Следующий шаг: домен, HTTPS и содержимое

Перейдите к инструкции подключения домена и HTTPS к этому WordPress. Она учитывает локальный адрес установки, PHP и замену адресов в базе. Общие материалы о привязке домена и бесплатном сертификате объясняют DNS и проверку продления.

Затем настройте Journal или Community и пройдите маршрут создания первого сайта. Новые бесплатные темы Hostfera будем представлять отдельными статьями после их выпуска.

Первоисточники

Нашли неточность?

Сообщите адрес статьи и фрагмент через контакты редакции.