Bu rehberde gerçek bir Ubuntu 24.04.4 LTS VPS üzerinde Docker Engine'i resmî repository'den kurduk, Compose ve Buildx'i doğruladık, hello-world ile gerçek container testi yaptık, Portainer CE LTS'i kalıcı volume ile ayağa kaldırdık, portainer.ekasunucu.com için Nginx reverse proxy ve Let's Encrypt SSL yapılandırdık, Certbot snap timeout sorununu belgeledik ve finalde 9443 portunu yalnız 127.0.0.1'e bind ederek yönetim arayüzünü güvenli hale getirdik.
Ubuntu 24.04.4 LTS
↓ Docker Engine + Compose
Docker socket /var/run/docker.sock
↓
Portainer CE LTS :9443
↓ localhost only
Nginx :443 + Let's Encrypt
↓
portainer.ekasunucu.comBu rehber gerçek bir Ubuntu 24.04.4 LTS VPS üzerinde yapılan kurulumun baştan sona kaydıdır. Test sırasında Docker Engine 29.7.2, Docker Compose v5.4.0 ve Portainer Community Edition 2.39.5 LTS çalıştırıldı; sürümler makalenin hazırlandığı test ortamını temsil eder.
Hedef yalnız Portainer'ı açmak değildi. Docker'ı resmî deposundan kurduk, Portainer verisini named volume üzerinde kalıcı tuttuk, Nginx'i ters vekil olarak konumlandırdık, Let's Encrypt TLS ekledik ve finalde Portainer 9443 portunu yalnız 127.0.0.1'e bind ederek ham yönetim portunu internetten kapattık.
Internet :443
↓
Nginx + Let's Encrypt
↓
https://127.0.0.1:9443
↓
Portainer CE LTS
↓
/var/run/docker.sock → Docker EngineKuruluma başlamadan önce Ubuntu sürümünü, kernel'i, mimariyi, RAM'i ve disk alanını kaydedin. Test VPS'imiz Ubuntu 24.04.4 LTS Noble, 6.8.0-137-generic kernel ve x86-64 mimarideydi.
Docker'ın resmî paketlerini kullanacaksanız daha önce kurulmuş docker.io, docker-compose, containerd, runc veya podman-docker gibi paketleri körlemesine karıştırmayın. Önce hangi paketlerin gerçekten kurulu olduğunu görün; üretim sunucusunda kaldırma işlemini mevcut iş yüklerini incelemeden uygulamayın.
cat /etc/os-release | grep -E 'PRETTY_NAME|VERSION_ID|VERSION_CODENAME'
uname -r
dpkg --print-architecturefree -h
df -h /dpkg --get-selections | grep -E 'docker|containerd|runc|podman' || trueDocker Engine'i Ubuntu'nun genel docker.io paketinden değil, Docker'ın resmî Ubuntu deposundan kurduk. Önce ca-certificates ve curl hazırlandı, Docker'ın imza anahtarı /etc/apt/keyrings/docker.asc altına alındı ve deb822 biçimindeki docker.sources dosyası oluşturuldu.
apt-cache policy docker-ce çıktısında Noble stable deposundan aday paket görünmesi, repository katmanının doğru çalıştığını gösterir. Testte aday Docker CE sürümü 29.7.2 idi.
apt-get update
apt-get install -y ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asccat >/etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
apt-get update
apt-cache policy docker-ceRepository doğrulamasından sonra docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin ve docker-compose-plugin paketlerini kurduk. Test oturumunda toplam 102 MB arşiv indirildi; bu boyut zaman ve paket sürümüne göre değişebilir.
Docker servisini systemd ile etkinleştirip hemen başlattık. Ardından Docker, Compose ve Buildx sürümlerini ayrı ayrı doğruladık. Böylece yalnız CLI dosyasının varlığını değil, gereken eklentilerin de kullanılabilir olduğunu gördük.
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginsystemctl enable --now docker
systemctl is-active dockerdocker --version
docker compose version
docker buildx versionİlk otomasyon scriptimiz Docker deposunu başarıyla görmesine rağmen yalnız çıktı kısaltmak için kullandığımız head -n 20 satırında exit code 141 ile kesildi. Docker repository veya paket yöneticisi bozuk değildi; pipeline'ın upstream tarafı head erken kapandığında SIGPIPE aldı ve set -o pipefail bunu script hatası kabul etti.
Görüntüleme amaçlı pipeline'larda sed -n gibi tüm girdiyi tüketen bir yöntem kullanabilir veya gerçekten zararsız olduğundan eminseniz ilgili gösterim komutuna || true ekleyebilirsiniz. Kurulum, doğrulama veya veri değiştiren komutların hatalarını bu yöntemle gizlemeyin.
apt-cache policy docker-ce | sed -n '1,20p'apt-cache policy docker-ce | head -n 20 || truedocker --version yalnız istemcinin kurulu olduğunu gösterir. Bu yüzden hello-world image'ını Docker Hub'dan çekip gerçek bir container çalıştırdık. 'Hello from Docker!' çıktısı istemci, daemon, image pull ve container çalıştırma zincirinin birlikte çalıştığını doğruladı.
docker info ile storage driver, cgroup, security options, Docker Root Dir ve sunucu kaynaklarını da kaydettik. Testte overlayfs, cgroup v2, AppArmor ve seccomp görüldü.
docker run --rm hello-worlddocker infosystemctl --failedPortainer yapılandırmasının container ömründen bağımsız kalması için önce portainer_data adlı Docker volume oluşturduk. Ardından portainer/portainer-ce:lts image'ını çektik ve Docker socket'i salt host bağlantısı olarak container içine mount ettik.
Gerçek ilk testte 9443 portunu kısa süreliğine host üzerinde yayınlayarak Portainer HTTPS endpointini doğruladık. Bu, final güvenlik modeli değildir; Nginx ve domain çalıştıktan sonra aynı container 127.0.0.1:9443 bind ile yeniden oluşturuldu.
docker volume create portainer_data
docker pull portainer/portainer-ce:ltsdocker run -d --name portainer --restart=always -p 9443:9443 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:ltsdocker ps --filter name='^/portainer$'
curl -k -sS -o /dev/null -w '%{http_code}\n' https://127.0.0.1:9443/Temiz Portainer veritabanında ilk açılış yönetici hesabı oluşturma ekranını gösterir. Testte Portainer logu ayrıca ilk admin kurulumu için geçici bir setup token üretti. Bu token, API anahtarı veya parola gibi hassas kabul edilmeli ve ekran görüntüsünde yayınlanmamalıdır.
Yönetici hesabını oluşturduktan sonra Environment Wizard yerel Docker ortamını algılar. İlk kurulum ekranı uzun süre açık bırakılırsa güvenlik nedeniyle setup oturumu kapanabilir; böyle bir durumda containerı yeniden başlatıp kuruluma devam edebilirsiniz.
docker logs portainer --tail 100docker restart portainerPortainer'ı doğrudan IP:9443 yerine portainer.ekasunucu.com üzerinden sunmak için Nginx ve dnsutils kurduk. Cloudflare DNS ve Google DNS sorgularında alan adı beklenen origin IP'ye çözülünce reverse proxy yapılandırmasına geçtik.
Nginx, istemci isteklerini 127.0.0.1:9443 üzerindeki Portainer HTTPS servisine iletir. Portainer varsayılan olarak kendi self-signed sertifikasını ürettiği için localhost upstream doğrulamasında proxy_ssl_verify off kullanıldı; internet tarafındaki gerçek TLS sertifikasını ise Nginx/Let's Encrypt yönetir.
apt-get update
apt-get install -y nginx dnsutils
systemctl enable --now nginxdig +short A portainer.ekasunucu.com @1.1.1.1
dig +short A portainer.ekasunucu.com @8.8.8.8cat >/etc/nginx/conf.d/portainer-websocket.conf <<'EOF'
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
EOFcat >/etc/nginx/sites-available/portainer.ekasunucu.com <<'EOF'
server {
listen 80;
listen [::]:80;
server_name portainer.ekasunucu.com;
location / {
proxy_pass https://127.0.0.1:9443;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_ssl_verify off;
}
}
EOF
ln -sfn /etc/nginx/sites-available/portainer.ekasunucu.com /etc/nginx/sites-enabled/portainer.ekasunucu.com
nginx -t
systemctl reload nginxcurl -sS -o /dev/null -w '%{http_code}\n' -H 'Host: portainer.ekasunucu.com' http://127.0.0.1/İlk snap install --classic certbot denememizde core24 paketi Canonical CDN'den indirilirken TCP 443 zaman aşımına uğradı. Bu hata Nginx veya Portainer reverse proxy'sinin bozuk olduğunu göstermiyordu; snap download katmanında geçici ağ/CDN erişim problemi vardı.
snap changes ve snapd servis durumuyla hatayı doğruladık. Bir sonraki denemede aynı Certbot snap kurulumu başarıyla tamamlandı ve 5.7.0 sürümü kullanılabilir hale geldi. Bu tür geçici ağ hatalarında yapılandırmayı gereksiz yere değiştirmeden önce tekrar deneme ve bağlantı teşhisi yapın.
snap changes
systemctl is-active snapdsnap install --classic certbotsnap list certbot
/snap/bin/certbot --versionSorun giderme sırasında Ubuntu APT deposundaki Certbot da kısa süre test edildi. Final yapılandırmada iki farklı Certbot kurulumunu aynı anda bırakmamak için apt ile gelen certbot, python3-certbot ve python3-certbot-nginx paketlerini kaldırıp snap Certbot 5.7.0 üzerinde standardize ettik.
Tek binary ve tek renewal mekanizması kullanmak, hangi certbot komutunun ve hangi timer'ın aktif olduğunu daha anlaşılır hale getirir. Mevcut bir sunucuda kaldırma yapmadan önce sertifika ve renewal yapılandırmalarınızı kontrol edin.
apt-get remove -y certbot python3-certbot python3-certbot-nginx python3-certbot || truesnap install --classic certbot
ln -sfn /snap/bin/certbot /usr/local/bin/certbot
certbot --versionNginx üzerinden HTTP reverse proxy 200 döndürdükten sonra Let's Encrypt sertifikasını aldık. Certbot Nginx eklentisi sertifikayı /etc/letsencrypt/live/portainer.ekasunucu.com altında sakladı ve site yapılandırmasına HTTPS bloklarını uyguladı.
Sertifika alındıktan sonra yalnız tarayıcıya güvenmek yerine nginx -t, HTTPS HTTP kodu ve openssl ile subject, issuer ve tarihleri doğruladık. Test sertifikası Let's Encrypt tarafından ECDSA anahtarla üretildi.
certbot --nginx -d portainer.ekasunucu.com -m [email protected] --agree-tos --no-eff-email --redirectnginx -t
systemctl is-active nginxcurl -I https://portainer.ekasunucu.com/openssl s_client -connect portainer.ekasunucu.com:443 -servername portainer.ekasunucu.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -datesDomain ve Nginx HTTPS zinciri çalıştıktan sonra Portainer containerını aynı portainer_data volume ile yeniden oluşturduk. Tek kritik fark host port eşlemesinin 127.0.0.1:9443:9443 olmasıdır. Böylece Portainer'ın yönetim portu doğrudan public IP üzerinde dinlemez.
Container silinip yeniden oluşturulsa da Portainer veritabanı named volume içinde kaldığı için yönetici hesabı ve yapılandırma korunur. Final ss çıktısında 9443 yalnız loopback'te, internet erişimi için 80/443 ise Nginx üzerinde görünmelidir.
docker stop portainer
docker rm portainerdocker run -d --name portainer --restart=always -p 127.0.0.1:9443:9443 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:ltsdocker ps --filter name='^/portainer$'
ss -lntp | grep -E ':(80|443|9443)\b'curl -k -sS -o /dev/null -w '%{http_code}\n' https://127.0.0.1:9443/
curl -sS -o /dev/null -w '%{http_code}\n' https://portainer.ekasunucu.com/Sertifika bugün çalışıyor diye üç ay sonra da otomatik yenileneceğini varsaymayın. Final kontrolde snap.certbot.renew timer'ın etkin olduğunu gördük ve certbot renew --dry-run ile gerçek yenileme simülasyonunu çalıştırdık.
Dry-run tüm simüle yenilemelerin başarılı olduğunu bildirdi. Nginx config testi ve sistem servis kontrolüyle birlikte bu, TLS tarafını üretime bırakmadan önce önemli bir doğrulamadır.
systemctl list-timers --all | grep -i certbot || truecertbot renew --dry-runnginx -tFinalde Portainer giriş ekranına yalnız https://portainer.ekasunucu.com adresinden eriştik. İlk yönetici hesabıyla oturum açtıktan sonra Environment Wizard yerel Docker socket bağlantısını algıladı ve local environment için Get Started akışını sundu.
Home ekranında local environment Up durumda görünürken container, volume ve image sayıları ile CPU/RAM kaynakları da görüntülendi. Böylece yalnız domainin açılmasını değil, Portainer'ın Docker Engine'i gerçekten yönetebildiğini de doğrulamış olduk.
https://portainer.ekasunucu.com


Kurulumun sonunda Docker ve Nginx servislerini, Portainer containerını, named volume'u, disk kullanımını, HTTPS HTTP kodunu ve failed systemd unit listesini ayrı ayrı kontrol edin. Test VPS'imizde final HTTP kodu 200 ve systemctl --failed sonucu sıfır hatalı unit idi.
Bu kontrolleri reboot sonrası tekrar etmek daha değerlidir. Özellikle Docker restart policy, Nginx autostart, Portainer container durumu ve domain TLS erişiminin kullanıcı oturumundan bağımsız olduğunu doğrulayın.
systemctl is-active docker nginx
docker ps
docker volume lsdocker system dfcurl -sS -o /dev/null -w 'HTTPS %{http_code}\n' https://portainer.ekasunucu.com/ss -lntp | grep -E ':(80|443|9443)\b'
systemctl --failedEvet. Bu rehberde Docker Engine 29.7.2 Ubuntu 24.04.4 LTS Noble üzerinde gerçek kurulumla çalıştırıldı. Yeni kurulumda Docker'ın resmî Ubuntu destek ve paket sayfasındaki güncel sürümü esas alın.
Docker CE, Compose ve Buildx paketlerini aynı üretici deposundan ve güncel plugin yapısıyla almak için resmî Docker Ubuntu repository'si kullanıldı.
docker --version yalnız istemciyi gösterir. hello-world testi daemon bağlantısı, image pull, container oluşturma ve çıktı zincirini birlikte doğrular.
Portainer kendi HTTPS servisini 9443 üzerinde çalıştırır. Bu rehberin finalinde host tarafında yalnız 127.0.0.1:9443 dinler; dış erişim Nginx 443 üzerinden yapılır.
Portainer'ın localhost upstream bağlantısındaki self-signed sertifikası Nginx arkasında kullanılabilir. Kullanıcıya sunulan public TLS sertifikası Let's Encrypt tarafından Nginx üzerinde sağlanır.
portainer_data named volume korunursa Portainer veritabanı ve kalıcı ayarlar containerdan bağımsız olarak saklanır. Volume'u silmeyin.
Temiz kurulumda ilk yönetici yapılandırmasını korumaya yarayan geçici hassas değerdir. Logda görülebilir; parolaya benzer şekilde gizli tutulmalıdır.
Önce snap changes, snapd ve 443 dış erişimini kontrol edin. Bizim gerçek testimizde Canonical CDN indirmesi zaman aşımına uğradı, daha sonraki tekrar denemesi başarılı oldu.
Bu rehberde final yapılandırmada hayır. Sorun giderme sonrası APT Certbot paketlerini kaldırıp snap Certbot üzerinde standardize ettik.
Nginx zaten 443 üzerinden güvenli domain erişimi sağladığı için Portainer'ın ham yönetim portunun public IP üzerinde ayrıca dinlemesine gerek yoktur. Loopback bind saldırı yüzeyini azaltır.
certbot renew --dry-run komutu gerçek sertifikayı değiştirmeden yenileme akışını simüle eder. Testimizde tüm simüle yenilemeler başarıyla tamamlandı.
Portainer ile aynı hosttaki /var/run/docker.sock mount edildiğinde Environment Wizard local Docker ortamını algılayabilir. İlk kurulum ekranında Get Started ile devam edilir.
Bu mimaride public web erişimi için Nginx 80/443 dinler; Portainer 9443 yalnız 127.0.0.1'de kalır. SSH ve diğer servisler kendi güvenlik politikanıza göre ayrıca yönetilir.
Root/SSH erişimli uygun bir Ubuntu VPS, yeterli RAM/disk ve doğru güvenlik politikasıyla aynı mimari uygulanabilir. Kaynak ihtiyacı çalıştıracağınız containerlara göre belirlenmelidir.
Docker Engine, Portainer, Nginx, Ollama, Open WebUI ve n8n gibi self-hosted servisleri kendi altyapınızda çalıştırmak için EKA Sunucu Linux VPS paketlerini inceleyebilirsiniz.
Güncellendi: 10.08.2026