Деплой Kotlin приложения на VPS: пошаговое руководство для продвинутых
Разработка на Kotlin — это лишь половина дела. Настоящее мастерство проявляется, когда ваше приложение начинает работать в production-среде на собственном VPS-сервере. В этой статье мы рассмотрим продвинутые техники деплоя Kotlin-приложений: от сборки fat JAR до настройки бесперебойной работы с systemd, обратного прокси через Nginx и автоматизации через CI/CD. Материал рассчитан на разработчиков, которые уже знакомы с основами Kotlin и хотят выйти на профессиональный уровень.
1. Подготовка production-сборки Kotlin-приложения
Первый шаг — создание оптимизированной сборки. Используем плагин shadow для Gradle, который упакует все зависимости в один исполняемый JAR-файл (fat JAR).
Добавьте в build.gradle.kts:
plugins {
kotlin("jvm") version "1.9.22"
id("com.github.johnrengelman.shadow") version "8.1.1"
application
}
application {
mainClass.set("com.example.MainKt")
}
tasks.shadowJar {
archiveBaseName.set("app")
archiveClassifier.set("")
archiveVersion.set("")
minimize()
}
Соберите JAR командой:
./gradlew shadowJar
В результате получите файл build/libs/app.jar. Для production рекомендуется отключить debug-логи и настроить уровень логирования через переменные окружения.
Пример конфигурации logback.xml для production:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/app/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/app/app.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</configuration>
2. Создание systemd-сервиса для автоматического запуска
Чтобы приложение автоматически запускалось при старте системы и перезапускалось при сбоях, используем systemd. Создайте файл /etc/systemd/system/kotlin-app.service:
[Unit]
Description=Kotlin Application Service
After=network.target
[Service]
Type=simple
User=appuser
Group=appuser
WorkingDirectory=/opt/kotlin-app
ExecStart=/usr/bin/java -Xms512m -Xmx1024m -jar /opt/kotlin-app/app.jar
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
Environment="APP_ENV=production"
Environment="DB_URL=jdbc:postgresql://localhost:5432/mydb"
[Install]
WantedBy=multi-user.target
После создания файла выполните:
sudo systemctl daemon-reload
sudo systemctl enable kotlin-app
sudo systemctl start kotlin-app
Проверьте статус:
sudo systemctl status kotlin-app
Логи можно смотреть через journalctl -u kotlin-app -f.
3. Настройка Nginx как обратного прокси с SSL
Nginx обеспечит балансировку, кэширование и HTTPS. Установите Nginx и Certbot:
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx
Создайте конфигурацию /etc/nginx/sites-available/kotlin-app:
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90;
}
location /static/ {
alias /opt/kotlin-app/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
Активируйте сайт и получите SSL-сертификат:
sudo ln -s /etc/nginx/sites-available/kotlin-app /etc/nginx/sites-enabled/
sudo certbot --nginx -d yourdomain.com
sudo systemctl restart nginx
4. Мониторинг и автоматический перезапуск
Даже с systemd полезно добавить мониторинг здоровья приложения. Создайте простой health-check endpoint в Kotlin:
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.routing.*
import io.ktor.http.*
import io.ktor.server.response.*
fun main() {
embeddedServer(Netty, port = 8080) {
routing {
get("/health") {
call.respondText("OK", ContentType.Text.Plain)
}
}
}.start(wait = true)
}
Добавьте в Nginx проверку здоровья:
location /health {
proxy_pass http://127.0.0.1:8080/health;
access_log off;
allow 127.0.0.1;
deny all;
}
Настройте мониторинг через systemd с опцией Restart=always и добавьте скрипт проверки в cron:
* * * * * /usr/bin/curl -f http://127.0.0.1:8080/health || systemctl restart kotlin-app
5. Настройка CI/CD с GitHub Actions
Автоматизируйте деплой через GitHub Actions. Создайте файл .github/workflows/deploy.yml:
name: Deploy Kotlin App
on:
push:
branches: [main]
jobs:
build: