Tomcat Kurulumu ve Java Web Uygulaması Yayınlama
Java ile bir web uygulaması geliştirdiniz, local’de mükemmel çalışıyor, şimdi sıra bunu gerçek bir sunucuda yayınlamaya geldi. İşte tam bu noktada Tomcat devreye giriyor. Apache Tomcat, Java Servlet ve JSP uygulamalarını çalıştırmak için kullanılan, endüstride onlarca yıldır kanıtlanmış bir uygulama sunucusudur. Bu yazıda sıfırdan Tomcat kurulumunu yapacak, güvenli bir şekilde yapılandıracak ve gerçek bir WAR dosyasını yayınlayacağız.
Ön Koşullar ve Ortam Hazırlığı
Tomcat’i kurmadan önce sistemde Java’nın kurulu olması gerekiyor. Tomcat 10.x için Java 11 veya üzeri önerilir. Önce mevcut Java kurulumunu kontrol edelim:
java -version
echo $JAVA_HOME
Eğer Java kurulu değilse Ubuntu/Debian için:
sudo apt update
sudo apt install -y openjdk-17-jdk
RHEL/CentOS/AlmaLinux için:
sudo dnf install -y java-17-openjdk-devel
Java kurduktan sonra JAVA_HOME değişkenini ayarlamak kritik önem taşıyor. Birçok Tomcat sorununun kökü eksik ya da yanlış JAVA_HOME tanımıdır:
# Java'nın nerede kurulu olduğunu bul
sudo update-alternatives --config java
# veya
readlink -f $(which java)
# /etc/environment veya /etc/profile.d/ altına ekle
echo 'JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' | sudo tee -a /etc/environment
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' | sudo tee /etc/profile.d/java.sh
source /etc/profile.d/java.sh
Tomcat İndirme ve Kurulum
Tomcat’i paket yöneticisi ile de kurabilirsiniz ama production ortamlarında resmi Apache sitesinden indirip elle kurmayı tercih ederim. Neden? Çünkü bu şekilde hangi versiyonu kullandığınızı tam olarak kontrol edersiniz ve güncellemeleri kendiniz yönetirsiniz.
Önce Tomcat için ayrı bir sistem kullanıcısı oluşturalım. Root ile Tomcat çalıştırmak ciddi bir güvenlik riskidir:
sudo useradd -r -m -U -d /opt/tomcat -s /bin/false tomcat
Şimdi Tomcat’i indirelim. Bu yazı yazılırken güncel versiyon 10.1.x’tir:
cd /tmp
wget https://downloads.apache.org/tomcat/tomcat-10/v10.1.20/bin/apache-tomcat-10.1.20.tar.gz
# Checksum doğrulaması yapmayı unutmayın
sha512sum apache-tomcat-10.1.20.tar.gz
# Arşivi aç ve taşı
sudo tar -xzf apache-tomcat-10.1.20.tar.gz -C /opt/tomcat --strip-components=1
# Sahipliği ayarla
sudo chown -R tomcat:tomcat /opt/tomcat
sudo chmod -R 750 /opt/tomcat
Systemd Servis Dosyası Oluşturma
Tomcat’i systemd servisi olarak tanımlamak; otomatik başlatma, log yönetimi ve izleme açısından işleri çok kolaylaştırır. Manuel startup.sh çalıştırmak production’da kabul edilemez:
sudo nano /etc/systemd/system/tomcat.service
Aşağıdaki içeriği yapıştırın:
[Unit]
Description=Apache Tomcat Web Application Container
After=network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64"
Environment="CATALINA_PID=/opt/tomcat/temp/tomcat.pid"
Environment="CATALINA_HOME=/opt/tomcat"
Environment="CATALINA_BASE=/opt/tomcat"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
Environment="JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom"
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
RestartSec=10
Restart=always
[Install]
WantedBy=multi-user.target
CATALINA_OPTS içindeki JVM parametrelerine dikkat edin. -Xms512M başlangıç heap boyutu, -Xmx1024M maksimum heap boyutudur. Sunucunuzun RAM’ine göre bu değerleri ayarlayın. Genel kural olarak toplam RAM’in yüzde 50-70’ini Tomcat’e verebilirsiniz.
sudo systemctl daemon-reload
sudo systemctl start tomcat
sudo systemctl enable tomcat
sudo systemctl status tomcat
Tomcat varsayılan olarak 8080 portunda çalışır. Tarayıcıdan http://sunucu-ip:8080 adresine giderek kurulumu doğrulayabilirsiniz.
Güvenlik Yapılandırması
Varsayılan Tomcat kurulumu production için hazır değildir. Birkaç kritik ayarı yapmadan uygulamanızı yayınlamayın.
Manager ve Host-Manager Uygulamalarını Koruma
/opt/tomcat/conf/tomcat-users.xml dosyasını düzenleyin:
sudo nano /opt/tomcat/conf/tomcat-users.xml
tagından önce şunları ekleyin:
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="admin-gui"/>
<user username="tomcatadmin"
password="GucluBirSifre123!"
roles="manager-gui,manager-script,admin-gui"/>
Önemli: Manager uygulamasına sadece localhost’tan erişimi kısıtlayın. Production’da manager uygulamasının internete açık olması saldırganların favori hedeflerinden biridir:
sudo nano /opt/tomcat/webapps/manager/META-INF/context.xml
<Context antiResourceLocking="false" privileged="true" >
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127.d+.d+.d+|::1|10.0.0.d+" />
</Context>
server.xml Güvenlik Ayarları
sudo nano /opt/tomcat/conf/server.xml
Dikkat etmeniz gereken noktalar:
- 8005 shutdown portu: Varsayılan
SHUTDOWNkomutunu değiştirin.satırını bulup anlamlı olmayan bir string yazın. - AJP connector’ı devre dışı bırakın: Nginx veya Apache reverse proxy kullanmıyorsanız AJP portunu (8009) kapatın.
<Connector protocol="AJP/1.3"ile başlayan satırı yorum satırına alın. - X-Powered-By header’ını gizleyin: Connector tanımına
xpoweredBy="false"ekleyin.
Nginx ile Reverse Proxy Kurulumu
Production ortamında Tomcat’i direkt olarak internete açmak yerine önüne Nginx koymanızı kesinlikle öneririm. Hem 80/443 portlarından erişim sağlar hem de SSL termination, rate limiting ve statik dosya servisi gibi avantajlar sunar:
sudo apt install -y nginx
sudo nano /etc/nginx/sites-available/myapp
upstream tomcat {
server 127.0.0.1:8080;
keepalive 32;
}
server {
listen 80;
server_name myapp.example.com;
# HTTP'den HTTPS'e yönlendir
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name myapp.example.com;
ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.example.com/privkey.pem;
# Güvenlik header'ları
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
location / {
proxy_pass http://tomcat;
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_connect_timeout 60s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
# Büyük dosya yükleme için
client_max_body_size 100M;
}
# Statik dosyalar için cache
location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ {
proxy_pass http://tomcat;
proxy_cache_valid 200 1d;
expires 1d;
add_header Cache-Control "public, immutable";
}
}
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
WAR Dosyasını Yayınlama
Asıl amacımıza geldik. Java web uygulamanızı WAR dosyası olarak paketleyip Tomcat’e deploy etmenin birkaç yöntemi var.
Yöntem 1: Webapps Dizinine Kopyalama
En basit yöntem WAR dosyasını doğrudan webapps dizinine atmak. Tomcat çalışırken otomatik olarak algılar ve deploy eder:
# Uygulamanızı build edin (Maven örneği)
mvn clean package -DskipTests
# WAR dosyasını kopyalayın
sudo cp target/myapp-1.0.0.war /opt/tomcat/webapps/myapp.war
sudo chown tomcat:tomcat /opt/tomcat/webapps/myapp.war
Tomcat WAR dosyasını otomatik extract edecek ve webapps/myapp/ dizini oluşacaktır. Uygulamaya http://sunucu:8080/myapp adresinden erişebilirsiniz.
ROOT context’te (yani / path’inde) çalıştırmak istiyorsanız WAR dosyasını ROOT.war olarak kopyalayın. Mevcut ROOT uygulamasını önce silmeyi unutmayın:
sudo rm -rf /opt/tomcat/webapps/ROOT
sudo cp target/myapp-1.0.0.war /opt/tomcat/webapps/ROOT.war
sudo chown tomcat:tomcat /opt/tomcat/webapps/ROOT.war
Yöntem 2: Manager API ile Uzak Deploy
CI/CD pipeline’larında çok işe yarayan bu yöntem, Tomcat’i yeniden başlatmadan uygulamayı güncelleyebilmenizi sağlar:
# Mevcut uygulamayı undeploy et
curl -u tomcatadmin:GucluBirSifre123!
"http://localhost:8080/manager/text/undeploy?path=/myapp"
# Yeni versiyonu deploy et
curl -u tomcatadmin:GucluBirSifre123!
-T target/myapp-1.0.0.war
"http://localhost:8080/manager/text/deploy?path=/myapp&update=true"
# Deploy durumunu kontrol et
curl -u tomcatadmin:GucluBirSifre123!
"http://localhost:8080/manager/text/list"
Yöntem 3: Context XML ile Yapılandırmalı Deploy
Daha fazla kontrol istiyorsanız conf/Catalina/localhost/ altına context XML dosyası oluşturun:
sudo nano /opt/tomcat/conf/Catalina/localhost/myapp.xml
<Context path="/myapp"
docBase="/opt/apps/myapp-1.0.0.war"
reloadable="false"
unpackWAR="true">
<!-- Veritabanı bağlantı havuzu örneği -->
<Resource name="jdbc/MyDB"
auth="Container"
type="javax.sql.DataSource"
maxTotal="20"
maxIdle="10"
maxWaitMillis="10000"
username="dbuser"
password="dbpassword"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://localhost:5432/mydb"/>
</Context>
Bu yöntemin güzel tarafı WAR dosyasını webapps dışında bir yerde tutabilmeniz ve JNDI kaynakları gibi ortama özgü yapılandırmaları uygulama kodundan ayırabilmenizdir.
Log Yönetimi ve Sorun Giderme
Tomcat deploy sırasında sorun yaşandığında ilk bakılacak yer log dosyalarıdır:
# Catalina ana log
sudo tail -f /opt/tomcat/logs/catalina.out
# Tarihli loglar
sudo ls -la /opt/tomcat/logs/
sudo tail -f /opt/tomcat/logs/localhost.$(date +%Y-%m-%d).log
# systemd journal üzerinden
sudo journalctl -u tomcat -f --since "10 minutes ago"
Sık karşılaşılan sorunlar ve çözümleri:
- ClassNotFoundException: Uygulama bağımlılığı WAR içinde yok demektir.
WEB-INF/lib/dizinini kontrol edin. - OutOfMemoryError: Java heap space:
CATALINA_OPTSiçindeki-Xmxdeğerini artırın. - Port already in use:
sudo ss -tlnp | grep 8080ile hangi process’in portu kullandığını bulun. - Permission denied on logs: Log dizini sahipliğini kontrol edin:
sudo chown -R tomcat:tomcat /opt/tomcat/logs
Deploy sonrası uygulamanın gerçekten ayakta olup olmadığını kontrol etmek için basit bir health check scripti yazabilirsiniz:
#!/bin/bash
# /usr/local/bin/tomcat-health-check.sh
APP_URL="http://localhost:8080/myapp/health"
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 $APP_URL)
if [ "$HTTP_CODE" -eq 200 ]; then
echo "$(date): Uygulama saglıklı - HTTP $HTTP_CODE"
exit 0
else
echo "$(date): UYARI - Uygulama yanıt vermiyor, HTTP kodu: $HTTP_CODE"
# Buraya bildirim mekanizması ekleyebilirsiniz
# systemctl restart tomcat # Otomatik yeniden başlatma
exit 1
fi
sudo chmod +x /usr/local/bin/tomcat-health-check.sh
# Cron ile her 5 dakikada bir çalıştır
echo "*/5 * * * * root /usr/local/bin/tomcat-health-check.sh >> /var/log/tomcat-health.log 2>&1" | sudo tee /etc/cron.d/tomcat-health
Performans Tuning İpuçları
Production’da Tomcat’in performansını artırmak için birkaç kritik ayar:
server.xml içindeki Connector tanımını optimize edin:
<Connector port="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
maxThreads="200"
minSpareThreads="25"
maxConnections="8192"
acceptCount="100"
compression="on"
compressionMinSize="2048"
compressibleMimeType="text/html,text/xml,text/plain,text/css,
application/javascript,application/json"
redirectPort="8443"/>
- maxThreads: Eşzamanlı istek sayısı. Genellikle 200-400 arası uygundur.
- minSpareThreads: Hazırda bekleyen minimum thread sayısı.
- compression: Gzip sıkıştırma, bant genişliği kullanımını yüzde 60-70 azaltabilir.
- maxConnections: Açık tutulabilecek maksimum bağlantı sayısı.
Sonuç
Tomcat kurulumu ve Java uygulaması deploy etmek, doğru adımları takip ettiğinizde oldukça sistematik bir süreçtir. Bu yazıda anlattıklarımızı özetleyecek olursak: ayrı bir sistem kullanıcısıyla güvenli kurulum, systemd entegrasyonu, Nginx reverse proxy ile üretim kalitesi bir yapı ve birden fazla deploy yöntemi.
En çok gördüğüm hata, insanların geliştirme ortamı yapılandırmasını production’a olduğu gibi taşımasıdır. Manager uygulamasını internete açık bırakmak, varsayılan şifreler kullanmak ve JVM parametrelerini hiç dokunmadan geçmek gereksiz sorunlara yol açar.
Bir sonraki adım olarak uygulamanızın deploy sürecini bir CI/CD aracına bağlamanızı öneririm. Jenkins veya GitLab CI ile Maven build ve Tomcat Manager API deploy adımlarını birleştirdiğinizde, kod push etmeniz yeterli olacak ve geri kalanı otomatik halledilecektir. Bu da geceleri rahat uyumanızı sağlar.
