Статьи Утилиты Telegram YouTube RuTube Отзывы

Настройка Ubuntu под хостинг JVM приложения

14 ноября 2024

Тэги: gradle, Java, Linux, maven, Nginx, PostgreSQL, Spring, SQL, руководство.

Содержание

  1. Установка и настройка Java
  2. Установка и настройка postgres
  3. Запускаем приложение как linux-сервис
  4. Настройка Nginx
  5. Настройка переадресации с www и http на https
  6. Настройка брандмауэра
  7. Заключение

Если Вам интересно, как настроить сервер для хостинга JVM приложения, то предлагаю вашему вниманию следующую инструкцию. Предположим, вы только что получили доступ к чистому VPS серверу, на котором крутится Ubuntu и вы хотите на нём развернуть полноценное JVM приложение, основанное на Spring. Для полноты картины мы настроим также локальный postgres и доступ извне по http.

Прежде всего обновляем индекс менеджера пакетов apt. У вас должно быть достаточно прав для выполнения sudo, а также ваш сервер должен иметь доступ в Интернет.

sudo apt update

Установка и настройка Java

Для работы нашего jvm-приложения сначала требуется установить виртуальную машину Java. Ставим последнюю LTS (long-term support – длительная поддержка) версию. На данный момент это Java 17.

# если планируем компилировать на сервере, то ставим JDK
sudo apt-get install openjdk-17-jdk
# если будем запускать уже скомпилированное приложение, то JRE
sudo apt-get install openjdk-17-jre
# затем проверяем, что по умолчанию установилась нужная версия
java -version

JDK – это Java Development Kit, т.е. версия Java для разработчиков. Включает в себя компилятор. JRE – это Java Runtime Environment, т.е. среда исполнения. Причём JDK включает в себя JRE. На сервере чаще всего достаточно поставить именно JRE.

Опционально можно вручную настроить переменную окружения JAVA_HOME в файле /etc/environment. Добавляем в конце файла на новой строке:

JAVA_HOME="/usr/bin/java"

Установка и настройка postgres

Ставим postgres.

sudo apt install postgres
# заходим в систему под пользователем postgres
sudo -i -u postgres
# создаём базу данных с нужным именем
createdb имя_базы
# создаём пользователя для этой БД
createuser имя_пользователя --interactive

При создании пользователя вам будет задан только один вопрос. Создать его как суперпользователя? То есть наделить его всей полнотой полномочий для работы с БД. Выбираем yes.

Что касается имени пользователя и базы, то называйте их как-то похожим образом. Например, mydb и mydb_user.

Теперь заходим в сам postgres, выполнив команду psql. По сути psql – это консольный вариант клиента БД, который позволяет выполнять любые sql команды при наличии прав.

Установим для только что созданного пользователя хороший пароль (не забывайте точку с запятой в конце):

alter user имя_пользователя with encrypted password 'pa$$w0rd';

Кстати, генератор паролей доступен на данном сайте в разделе «Утилиты».

Выходим из psql командой \q.

Теперь в конце файла /etc/postgresql/номер_версии/main/pg_hba.conf добавляем:

host    база    пользователь       all                     password

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

Теперь если нам требуется подключаться к данной БД снаружи, а не только из самого приложения, работающего на этом же хосте, находим в файле /etc/postgresql/номер_версии/main/postgresql.conf
следующую закомментированную строку и раскомментируем её:

# listen_addresses = ‘*’;

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

Чтобы все изменения вступили в силу, перезапускаем postgres:

sudo service postgresql restart

Запускаем приложение как linux-сервис

Для начала нам нужно, чтобы имя jar-файла, которое получается в результате компиляции нашего Spring-приложения, не менялось от версии к версии. Задать его в явном виде в gradle можно так:

// файл build.gradle.kts
tasks {
   bootJar {
       archiveFileName.set("ИМЯ.jar")
   }
}

Если вы используете maven, то используйте следующую настройку:

<!-- файл pom.xml -->
<build>
   <plugins>
       <plugin>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-maven-plugin</artifactId>
           <configuration>
               <finalName>ИМЯ</finalName>
           </configuration>
       </plugin>
   </plugins>
</build>

Предположим, у нас уже есть скомпилированное jvm-приложение, которое умеет слушать порт 8080. Чтобы это приложение всё время работало на сервере и автоматически запускалось при старте сервера, нужно зарегистрировать его как linux-сервис.

Для этого с помощью scp копируем jar-файл (если их несколько, копируем тот, который больше) на сервер. Например, в папку /var/имя_приложения/имя_приложения.jar

Затем в папке /etc/systemd/system/ создаём файл имя_приложения.service со следующим содержимым:

[Unit]
Description=описание
After=syslog.target

[Service]
User=имя_пользователя
Environment="КЛЮЧ=ЗНАЧЕНИЕ"
Environment="LOGGING_FILE_PATH=/var/log/имя_приложения/"
Environment="TZ=Europe/Moscow"
ExecStart=/usr/bin/java -jar /var/имя_приложения/имя_приложения.jar

[Install]
WantedBy=multi-user.target

Тут в параметре User указывайте, под каким пользователем системы следует запускать сервис. Разумеется, у него должны быть права на это.

В параметрах Environment вы можете задавать различные переменные окружения в формате «ключ=значение». В данном примере уже задан часовой пояс (TZ) и путь до папки с логами (LOGGING_FILE_PATH). Именно здесь вы можете указать профиль приложения test или prod.

В ExecStart указывается команда для запуска приложения. Здесь просто подставьте ваши значения.

Сохраняем файл, после чего активируем сервис и запускаем его:

# активация
sudo systemctl enable имя_сервиса.service
# первичный запуск
sudo service имя_сервиса start

Теперь наш сервис будет запускаться автоматически даже при перезагрузке сервера.

Если будете менять какие-то настройки в service-файле, не забывайте выполнять команду systemctl daemon-reload, чтобы изменения вступали в силу.

Настройка Nginx

Поскольку наш сервис слушает порт 8080, вы уже можете обращаться к нему снаружи, указав имя хоста или ip-адрес и порт 8080. Но как сделать так, чтобы порт не нужно было указывать в явном виде? В этом нам поможет Nginx, который будет проксировать все запросы с дефолтного порта 80 на порт нашего приложения 8080.

# ставим Nginx
sudo apt install nginx

Теперь открываем конфигурацию /etc/nginx/nginx.conf и находим там секцию http. Внутри неё нужно разместить секцию server:

http {

    server {
        listen 80;
        server_name домен;

        location / {
            proxy_pass http://127.0.0.1:8080/;
        }
    }
...
}

listen 80 указывает, что мы хотим слушать порт 80. Секция «location /» говорит о том, что все запросы с корня url мы перенаправляем на localhost на порт 8080 (параметр proxy_pass).

# проверяем, что не ошиблись в синтаксисе конфигурации
sudo nginx -t
# перечитываем конфиг
sudo nginx -s reload
# удаляем дефолтную страницу-заглушку - она нам больше не нужна
sudo rm /etc/nginx/sites-enabled/default

Теперь в урле при обращении к нашему сервису порт указывать не нужно.

Настройка переадресации с www и http на https

Если у вас настроен https с помощью сертификата Let's Encrypt или какого-то другого, имеет смысл на уровне nginx также настроить переадресацию, чтобы по умолчанию пользователей перекидывало с http на https. Также желательно настроить переадресацию с www в корень. Это полезно и с точки зрения индексации поисковиками, и с точки зрения удобства пользователей.

Для этого немного модифицируем секцию server в конфиге nginx.

server {
    listen 80;
    server_name домен www.домен;
    rewrite ^/(.*)/$ /$1 permanent;

    if ($scheme = http) {
        return 301 https://$server_name$request_uri;
    }
    if ($host ~* www\.(.*)) {
        set $host_without_www $1;
        rewrite ^(.*)$ http://$host_without_www$1 permanent;
    }

    location / {
        proxy_pass http://127.0.0.1:8080/;
    }

Не забудьте вместо «домен» подставить ваш домен. И тогда после перезагрузки nginx вы получите автоматический 301 редирект с http на https, а также редирект с поддомена www на основной домен.

Настройка брандмауэра

Напоследок было бы неплохо настроить хоть какую-то защиту нашего сервера. Воспользуемся стандартным брандмауэром UFW (Uncomplicated Firewall). По умолчанию он разрешает все подключения изнутри наружу и запрещает все подключения снаружи к серверу. Установка и настройка его предельно проста.

# установка
sudo apt install ufw
# Важно! Разрешаем ssh-подключения!
sudo ufw allow ssh

Команда вида «ufw allow протокол» позволяет разрешить подключения на определённый порт извне. Прежде всего, не забудьте разрешить ssh-подключение. Если вы забудете это сделать, то после активации ufw вы потеряете доступ к серверу.

Разрешим ещё несколько протоколов:

# разрешаем http и https протоколы (порты 80 и 443)
sudo ufw allow http
sudo ufw allow https
# разрешаем postgres на порту 5432
sudo ufw allow postgres
# включаем брандмауэр
sudo ufw enable

После активации брандмауэра все запрещённые порты окажутся недоступны!

Заключение

Мы рассмотрели вопросы установки Java и postgres на сервер с Ubuntu. Также разобрались как запускать наше Spring-приложение в качестве linux-сервиса. После этого научились пробрасывать запросы с порта 80 на порт нашего приложения с помощью Nginx. Узнали, как сделать 301 редирект с http на https в случае, если у вас установлен сертификат. Ну и, напоследок, ограничили доступ к серверу с помощью брандмауэра UFW.

Если вы обнаружите неточности или у вас есть дополнения – пишите их в комментах.



Комментарии

25.05.2022 12:34 Артур

Супер, замечательная, подробная статья!
Такую бы статью встретить чуть пораньше, сэкономил бы часть времени)
Большое спасибо!

18.11.2024 23:48 devmark

Добавил раздел "Настройка переадресации с www и http на https" в nginx.

Добавить комментарий

×

devmark.ru