Статьи
YouTube-канал

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

23 марта 2022

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

Содержание

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

Если Вам интересно, как настроить сервер для хостинга 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

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

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

Напоследок было бы неплохо настроить хоть какую-то защиту нашего сервера. Воспользуемся стандартным брандмауэром 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. И, напоследок, рассмотрели вопросы ограничения доступа с помощью брандмауэра UFW.

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


Облако тэгов

Kotlin, Java, Java 16, Java 11, Java 10, Java 9, Java 8, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.

Последние статьи


Комментарии

25.05.2022 12:34 Артур

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

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

×

devmark.ru