{"id":3647,"date":"2025-12-29T15:44:16","date_gmt":"2025-12-29T12:44:16","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/github-actions-ile-vpse-otomatik-deploy-ve-zero-downtime-yayin\/"},"modified":"2025-12-29T15:44:16","modified_gmt":"2025-12-29T12:44:16","slug":"github-actions-ile-vpse-otomatik-deploy-ve-zero-downtime-yayin","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/github-actions-ile-vpse-otomatik-deploy-ve-zero-downtime-yayin\/","title":{"rendered":"GitHub Actions ile VPS\u2019e Otomatik Deploy ve Zero\u2011Downtime Yay\u0131n"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#GitHub_Actions_ile_VPS_Deploy_Neden_Bu_Kadar_Kritik_Hale_Geldi\"><span class=\"toc_number toc_depth_1\">1<\/span> GitHub Actions ile VPS Deploy Neden Bu Kadar Kritik Hale Geldi?<\/a><\/li><li><a href=\"#Genel_Mimari_GitHub_Actions_VPS_Akisi_Nasil_Kurulur\"><span class=\"toc_number toc_depth_1\">2<\/span> Genel Mimari: GitHub Actions \u2192 VPS Ak\u0131\u015f\u0131 Nas\u0131l Kurulur?<\/a><ul><li><a href=\"#Branch_Stratejisi_ve_Ortamlar\"><span class=\"toc_number toc_depth_2\">2.1<\/span> Branch Stratejisi ve Ortamlar<\/a><\/li><li><a href=\"#Guvenlik_Perspektifi_SSH_Anahtari_ve_Deploy_Kullanicisi\"><span class=\"toc_number toc_depth_2\">2.2<\/span> G\u00fcvenlik Perspektifi: SSH Anahtar\u0131 ve Deploy Kullan\u0131c\u0131s\u0131<\/a><\/li><\/ul><\/li><li><a href=\"#VPS_Tarafi_Hazirligi_Dizin_Yapisi_systemd_ve_NginxPHP-FPM\"><span class=\"toc_number toc_depth_1\">3<\/span> VPS Taraf\u0131 Haz\u0131rl\u0131\u011f\u0131: Dizin Yap\u0131s\u0131, systemd ve Nginx\/PHP-FPM<\/a><ul><li><a href=\"#Standart_Dizin_Yapisi\"><span class=\"toc_number toc_depth_2\">3.1<\/span> Standart Dizin Yap\u0131s\u0131<\/a><\/li><li><a href=\"#PHP_Uygulamasi_Icin_Ornek_Nginx_Konfigurasyonu\"><span class=\"toc_number toc_depth_2\">3.2<\/span> PHP Uygulamas\u0131 \u0130\u00e7in \u00d6rnek Nginx Konfig\u00fcrasyonu<\/a><\/li><li><a href=\"#Nodejs_Uygulamasi_Icin_systemd_Servisi\"><span class=\"toc_number toc_depth_2\">3.3<\/span> Node.js Uygulamas\u0131 \u0130\u00e7in systemd Servisi<\/a><\/li><\/ul><\/li><li><a href=\"#GitHub_Actions_Temelleri_Workflow_Secrets_ve_Ortamlar\"><span class=\"toc_number toc_depth_1\">4<\/span> GitHub Actions Temelleri: Workflow, Secrets ve Ortamlar<\/a><ul><li><a href=\"#Gerekli_Secrets_Ornekleri\"><span class=\"toc_number toc_depth_2\">4.1<\/span> Gerekli Secrets \u00d6rnekleri<\/a><\/li><\/ul><\/li><li><a href=\"#PHP_LaravelSymfony_Icin_Ornek_GitHub_Actions_Workflow\"><span class=\"toc_number toc_depth_1\">5<\/span> PHP (Laravel\/Symfony) \u0130\u00e7in \u00d6rnek GitHub Actions Workflow<\/a><ul><li><a href=\"#1_Build_ve_Test_Asamasi\"><span class=\"toc_number toc_depth_2\">5.1<\/span> 1. Build ve Test A\u015famas\u0131<\/a><\/li><li><a href=\"#2_Build_Ciktisini_Paketleyip_VPSe_Gondermek\"><span class=\"toc_number toc_depth_2\">5.2<\/span> 2. Build \u00c7\u0131kt\u0131s\u0131n\u0131 Paketleyip VPS\u2019e G\u00f6ndermek<\/a><\/li><li><a href=\"#3_Sunucu_Uzerinde_Yeni_Surumu_Hazirlamak\"><span class=\"toc_number toc_depth_2\">5.3<\/span> 3. Sunucu \u00dczerinde Yeni S\u00fcr\u00fcm\u00fc Haz\u0131rlamak<\/a><\/li><\/ul><\/li><li><a href=\"#Nodejs_Icin_ZeroDowntime_GitHub_Actions_Workflow\"><span class=\"toc_number toc_depth_1\">6<\/span> Node.js \u0130\u00e7in Zero\u2011Downtime GitHub Actions Workflow<\/a><ul><li><a href=\"#1_Build_ve_Test\"><span class=\"toc_number toc_depth_2\">6.1<\/span> 1. Build ve Test<\/a><\/li><li><a href=\"#2_Build_Ciktisini_Gonderme_ve_Servisi_Yenileme\"><span class=\"toc_number toc_depth_2\">6.2<\/span> 2. Build \u00c7\u0131kt\u0131s\u0131n\u0131 G\u00f6nderme ve Servisi Yenileme<\/a><\/li><\/ul><\/li><li><a href=\"#Rollback_BlueGreen_ve_Canary_Isler_Sarpa_Sarinca_Ne_Yapacagiz\"><span class=\"toc_number toc_depth_1\">7<\/span> Rollback, Blue\u2011Green ve Canary: \u0130\u015fler Sarpa Sar\u0131nca Ne Yapaca\u011f\u0131z?<\/a><ul><li><a href=\"#Basit_Rollback_Stratejisi\"><span class=\"toc_number toc_depth_2\">7.1<\/span> Basit Rollback Stratejisi<\/a><\/li><\/ul><\/li><li><a href=\"#CICD_Surecini_Destekleyen_Ek_Adimlar_Git_Load_Test_ve_Izleme\"><span class=\"toc_number toc_depth_1\">8<\/span> CI\/CD S\u00fcrecini Destekleyen Ek Ad\u0131mlar: Git, Load Test ve \u0130zleme<\/a><ul><li><a href=\"#Git_ile_Otomatik_Deploy_Kulturu\"><span class=\"toc_number toc_depth_2\">8.1<\/span> Git ile Otomatik Deploy K\u00fclt\u00fcr\u00fc<\/a><\/li><li><a href=\"#Yuk_Testi_ve_Kapasite_Analizi\"><span class=\"toc_number toc_depth_2\">8.2<\/span> Y\u00fck Testi ve Kapasite Analizi<\/a><\/li><\/ul><\/li><li><a href=\"#DCHost_Uzerinde_Ornek_Senaryo_PHP_API_Nodejs_Frontend\"><span class=\"toc_number toc_depth_1\">9<\/span> DCHost \u00dczerinde \u00d6rnek Senaryo: PHP API + Node.js Frontend<\/a><\/li><li><a href=\"#Sonuc_ve_Sonraki_Adimlar_Kucuk_Bir_YAML_Buyuk_Bir_Rahatlik\"><span class=\"toc_number toc_depth_1\">10<\/span> Sonu\u00e7 ve Sonraki Ad\u0131mlar: K\u00fc\u00e7\u00fck Bir YAML, B\u00fcy\u00fck Bir Rahatl\u0131k<\/a><\/li><\/ul><\/div>\n<h2><span id=\"GitHub_Actions_ile_VPS_Deploy_Neden_Bu_Kadar_Kritik_Hale_Geldi\">GitHub Actions ile <a href=\"https:\/\/www.dchost.com\/tr\/vps\">VPS<\/a> Deploy Neden Bu Kadar Kritik Hale Geldi?<\/span><\/h2>\n<p>Geli\u015ftirme ekibinizin haftal\u0131k planlama toplant\u0131s\u0131nda, konu\u015fulan konular b\u00fcy\u00fck ihtimalle \u015funlar: \u201cHangi \u00f6zelli\u011fi yeti\u015ftirece\u011fiz?\u201d, \u201cTestler neden yava\u015f?\u201d, \u201cCanl\u0131da kesinti olmadan nas\u0131l g\u00fcncelleme yapar\u0131z?\u201d. Kod yazmak art\u0131k i\u015fin sadece bir k\u0131sm\u0131. As\u0131l de\u011fer, o kodun <strong>h\u0131zl\u0131, g\u00fcvenli ve kesinti olmadan<\/strong> canl\u0131 ortama ula\u015fmas\u0131nda ortaya \u00e7\u0131k\u0131yor. \u0130\u015fte tam bu noktada GitHub Actions ile VPS\u2019e otomatik deploy, \u00f6zellikle PHP ve Node.js projeleri i\u00e7in oyunu tamamen de\u011fi\u015ftiriyor.<\/p>\n<p>Manuel FTP ile dosya atmak, uzak masa\u00fcst\u00fc ile sunucuya ba\u011flan\u0131p klas\u00f6r kopyalamak, \u201cyanl\u0131\u015f dosyay\u0131 sildim\u201d pani\u011fi ya\u015famak istemiyorsan\u0131z; s\u00fcr\u00fcm kontroll\u00fc bir CI\/CD hatt\u0131 kurmak art\u0131k bir l\u00fcks de\u011fil, zorunluluk. DCHost olarak biz de kendi i\u00e7 projelerimizde ve m\u00fc\u015fterilerimizin altyap\u0131lar\u0131nda <strong>GitHub Actions \u2192 VPS<\/strong> ak\u0131\u015f\u0131n\u0131 standart hale getiriyoruz. Bu yaz\u0131da, PHP ve Node.js uygulamalar\u0131n\u0131 <strong>zero\u2011downtime<\/strong> (s\u0131f\u0131ra yak\u0131n kesinti) ile nas\u0131l yay\u0131nlayabilece\u011finizi, ad\u0131m ad\u0131m ve pratik \u00f6rneklerle anlataca\u011f\u0131m.<\/p>\n<p>Odak noktam\u0131z \u015fu olacak: GitHub Actions i\u00e7inde build ve test i\u015flemlerini yapmak, \u00e7\u0131kt\u0131y\u0131 DCHost \u00fczerindeki VPS\u2019inize g\u00f6ndermek, sunucuda <strong>sembolik s\u00fcr\u00fcmler (releases + current symlink)<\/strong> ile atomik ge\u00e7i\u015f sa\u011flamak ve gerekti\u011finde tek komutla rollback yapabilmek.<\/p>\n<h2><span id=\"Genel_Mimari_GitHub_Actions_VPS_Akisi_Nasil_Kurulur\">Genel Mimari: GitHub Actions \u2192 VPS Ak\u0131\u015f\u0131 Nas\u0131l Kurulur?<\/span><\/h2>\n<p>\u00d6nce b\u00fcy\u00fck resmi netle\u015ftirelim. Sa\u011fl\u0131kl\u0131 bir CI\/CD hatt\u0131nda tipik ak\u0131\u015f \u015f\u00f6yle g\u00f6r\u00fcn\u00fcr:<\/p>\n<ul>\n<li>Geli\u015ftirici, GitHub deposunda <strong>main<\/strong> veya <strong>production<\/strong> bran\u015f\u0131na kod g\u00f6nderir (push veya pull request merge).<\/li>\n<li>GitHub Actions workflow\u2019u tetiklenir: testler, lint, build, statik analiz \u00e7al\u0131\u015f\u0131r.<\/li>\n<li>Build ba\u015far\u0131l\u0131ysa, workflow VPS\u2019e g\u00fcvenli SSH ba\u011flant\u0131s\u0131 kurar.<\/li>\n<li>VPS \u00fczerinde yeni bir <code>release<\/code> klas\u00f6r\u00fc olu\u015fturulur, dosyalar buraya kopyalan\u0131r.<\/li>\n<li>Gerekli <strong>migrate, cache clear, build<\/strong> komutlar\u0131 sunucu taraf\u0131nda \u00e7al\u0131\u015f\u0131r.<\/li>\n<li><code>current<\/code> sembolik linki, eski s\u00fcr\u00fcmden yeni s\u00fcr\u00fcme atomik olarak kayd\u0131r\u0131l\u0131r.<\/li>\n<li>PHP-FPM, Node.js servisi veya reverse proxy\u2019ye hafif bir reload verilir.<\/li>\n<\/ul>\n<p>Bu yakla\u015f\u0131m\u0131, <a href=\"https:\/\/www.dchost.com\/blog\/vpse-sifir-kesinti-ci-cd-nasil-kurulur-rsync-sembolik-surumler-ve-systemd-ile-sicacik-bir-yolculuk\/\">VPS\u2019e s\u0131f\u0131r kesinti CI\/CD kurulumunu rsync ve sembolik s\u00fcr\u00fcmlerle anlatt\u0131\u011f\u0131m\u0131z rehberde<\/a> genel hatlar\u0131yla ele alm\u0131\u015ft\u0131k. Bu yaz\u0131da ise \u00f6zellikle <strong>GitHub Actions YAML<\/strong> taraf\u0131n\u0131, PHP ve Node.js \u00f6rnekleriyle detayland\u0131r\u0131yoruz.<\/p>\n<h3><span id=\"Branch_Stratejisi_ve_Ortamlar\">Branch Stratejisi ve Ortamlar<\/span><\/h3>\n<p>Basit ama i\u015f g\u00f6ren bir kurgu \u015f\u00f6yle olabilir:<\/p>\n<ul>\n<li><code>develop<\/code>: Geli\u015ftirme ortam\u0131na (staging) otomatik deploy.<\/li>\n<li><code>main<\/code> veya <code>master<\/code>: Canl\u0131 ortama otomatik veya onayl\u0131 deploy.<\/li>\n<\/ul>\n<p>GitHub Actions taraf\u0131nda <code>environments<\/code> kullanarak <strong>&#8220;staging&#8221;<\/strong> ve <strong>&#8220;production&#8221;<\/strong> ortamlar\u0131n\u0131 tan\u0131mlayabilir, production deploy\u2019lar\u0131n\u0131 manuel onaya ba\u011flayabilirsiniz.<\/p>\n<h3><span id=\"Guvenlik_Perspektifi_SSH_Anahtari_ve_Deploy_Kullanicisi\">G\u00fcvenlik Perspektifi: SSH Anahtar\u0131 ve Deploy Kullan\u0131c\u0131s\u0131<\/span><\/h3>\n<p>VPS\u2019e do\u011frudan <code>root<\/code> ile ba\u011flanmak yerine, sadece deploy i\u015flerine \u00f6zel, yetkisi s\u0131n\u0131rl\u0131 bir kullan\u0131c\u0131 kullanmak en sa\u011fl\u0131kl\u0131s\u0131d\u0131r. Bunu, <a href=\"https:\/\/www.dchost.com\/blog\/vps-sunucu-guvenligi-nasil-saglanir-kapiyi-acik-birakmadan-yasamanin-sirri\/\">VPS sunucu g\u00fcvenli\u011fini pratik \u015fekilde anlatt\u0131\u011f\u0131m\u0131z yaz\u0131da<\/a> geni\u015f bi\u00e7imde i\u015flemi\u015ftik. \u00d6zetle:<\/p>\n<ul>\n<li>DCHost VPS\u2019inizde <code>deploy<\/code> isminde yeni bir kullan\u0131c\u0131 a\u00e7\u0131n.<\/li>\n<li>Bu kullan\u0131c\u0131y\u0131 sadece ilgili proje dizinine yazma yetkisi olacak \u015fekilde k\u0131s\u0131tlay\u0131n.<\/li>\n<li>SSH eri\u015fimini sadece <strong>anahtar tabanl\u0131<\/strong> kimlik do\u011frulama ile s\u0131n\u0131rland\u0131r\u0131n.<\/li>\n<\/ul>\n<h2><span id=\"VPS_Tarafi_Hazirligi_Dizin_Yapisi_systemd_ve_NginxPHP-FPM\">VPS Taraf\u0131 Haz\u0131rl\u0131\u011f\u0131: Dizin Yap\u0131s\u0131, systemd ve Nginx\/PHP-FPM<\/span><\/h2>\n<p>GitHub Actions ile otomatik deploy\u2019un rahat etmesi i\u00e7in, sunucu taraf\u0131n\u0131 bir kez d\u00fczg\u00fcn kurman\u0131z yeterli. Sonras\u0131 k\u00fc\u00e7\u00fck iyile\u015ftirmeler.<\/p>\n<h3><span id=\"Standart_Dizin_Yapisi\">Standart Dizin Yap\u0131s\u0131<\/span><\/h3>\n<p>\u00d6rnek bir proje yolu \u00fczerinden gidelim:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">\/var\/www\/myapp\n  \u251c\u2500\u2500 releases\n  \u2502   \u251c\u2500\u2500 20250101010101\n  \u2502   \u251c\u2500\u2500 20250102123045\n  \u2502   \u2514\u2500\u2500 ...\n  \u251c\u2500\u2500 shared\n  \u2502   \u251c\u2500\u2500 .env\n  \u2502   \u251c\u2500\u2500 storage  (PHP i\u00e7in)\n  \u2502   \u2514\u2500\u2500 uploads  (Node.js statik i\u00e7erikleri vs.)\n  \u2514\u2500\u2500 current -&gt; \/var\/www\/myapp\/releases\/20250102123045\n<\/code><\/pre>\n<p>Zero\u2011downtime\u2019\u0131n kalbi buras\u0131. <code>current<\/code> sembolik linki her yeni s\u00fcr\u00fcmde ba\u015fka bir klas\u00f6re i\u015faret edecek. Nginx, PHP-FPM veya Node.js servisiniz hep <code>\/var\/www\/myapp\/current<\/code> yolunu g\u00f6recek; siz arka planda <code>releases<\/code> klas\u00f6r\u00fcnde yeni s\u00fcr\u00fcm\u00fc haz\u0131rlay\u0131p, en son symlink\u2019i saniyeler i\u00e7inde kayd\u0131racaks\u0131n\u0131z.<\/p>\n<h3><span id=\"PHP_Uygulamasi_Icin_Ornek_Nginx_Konfigurasyonu\">PHP Uygulamas\u0131 \u0130\u00e7in \u00d6rnek Nginx Konfig\u00fcrasyonu<\/span><\/h3>\n<p>Laravel veya ba\u015fka bir modern PHP framework\u2019\u00fc i\u00e7in basit bir Nginx konfig\u00fcrasyonu \u015f\u00f6yle olabilir:<\/p>\n<pre class=\"language-nginx line-numbers\"><code class=\"language-nginx\">server {\n    server_name example.com;\n    root \/var\/www\/myapp\/current\/public;\n\n    index index.php;\n\n    location \/ {\n        try_files $uri $uri\/ \/index.php?$query_string;\n    }\n\n    location ~ .php$ {\n        include fastcgi_params;\n        fastcgi_pass unix:\/run\/php\/php8.2-fpm.sock;\n        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;\n        fastcgi_param DOCUMENT_ROOT $realpath_root;\n    }\n}\n<\/code><\/pre>\n<p>Burada kritik nokta: <code>root<\/code> her zaman <code>current\/public<\/code>\u2019i i\u015faret ediyor. Deploy s\u0131ras\u0131nda <code>releases<\/code> klas\u00f6r\u00fcnde ne yaparsan\u0131z yap\u0131n, Nginx taraf\u0131 bunu fark etmeden yoluna devam ediyor.<\/p>\n<h3><span id=\"Nodejs_Uygulamasi_Icin_systemd_Servisi\">Node.js Uygulamas\u0131 \u0130\u00e7in systemd Servisi<\/span><\/h3>\n<p>Node.js projelerinde s\u00fcre\u00e7 y\u00f6netimi i\u00e7in <code>systemd<\/code> veya PM2 kullanabilirsiniz. PM2 taraf\u0131n\u0131 <a href=\"https:\/\/www.dchost.com\/blog\/node-jsi-canliya-alirken-panik-yapma-pm2-systemd-nginx-ssl-ve-sifir-kesinti-deploy-nasil-kurulur\/\">Node.js\u2019i canl\u0131ya al\u0131rken panik yapmama rehberimizde<\/a> detayl\u0131 anlatt\u0131k. Burada sade bir systemd \u00f6rne\u011fi verelim:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">[Unit]\nDescription=MyApp Node.js Service\nAfter=network.target\n\n[Service]\nUser=deploy\nGroup=deploy\nWorkingDirectory=\/var\/www\/myapp\/current\nExecStart=\/usr\/bin\/node dist\/server.js\nRestart=always\nEnvironment=NODE_ENV=production\nEnvironment=PORT=3000\n\n[Install]\nWantedBy=multi-user.target\n<\/code><\/pre>\n<p>Zero\u2011downtime i\u00e7in, yeni s\u00fcr\u00fcm\u00fc <code>releases<\/code> alt\u0131nda haz\u0131rlay\u0131p <code>current<\/code> symlink\u2019ini kayd\u0131rd\u0131ktan sonra <code>systemctl reload-or-restart myapp<\/code> kullanaca\u011f\u0131z. Do\u011fru kurguland\u0131\u011f\u0131nda, kesinti s\u00fcresi milisaniyelerle s\u0131n\u0131rl\u0131 kal\u0131r.<\/p>\n<h2><span id=\"GitHub_Actions_Temelleri_Workflow_Secrets_ve_Ortamlar\">GitHub Actions Temelleri: Workflow, Secrets ve Ortamlar<\/span><\/h2>\n<p>\u015eimdi GitHub taraf\u0131n\u0131 toparlayal\u0131m. Bir workflow dosyas\u0131 tipik olarak <code>.github\/workflows\/deploy.yml<\/code> alt\u0131nda durur ve a\u015fa\u011f\u0131daki bile\u015fenlerden olu\u015fur:<\/p>\n<ul>\n<li><strong>on<\/strong>: Hangi olaylarda tetiklenece\u011fi (push, pull_request, manual dispatch vb.).<\/li>\n<li><strong>jobs<\/strong>: build, test, deploy gibi i\u015fleri tan\u0131mlayan bloklar.<\/li>\n<li><strong>runs-on<\/strong>: Workflow\u2019un ko\u015faca\u011f\u0131 runner (genellikle GitHub\u2019\u0131n hosted runner\u2019lar\u0131).<\/li>\n<li><strong>secrets<\/strong>: VPS bilgileri, SSH anahtarlar\u0131, veritaban\u0131 \u015fifreleri.<\/li>\n<\/ul>\n<h3><span id=\"Gerekli_Secrets_Ornekleri\">Gerekli Secrets \u00d6rnekleri<\/span><\/h3>\n<p>GitHub deposu ayarlar\u0131ndan \u015fu secrets de\u011ferlerini tan\u0131mlaman\u0131z\u0131 \u00f6neririm:<\/p>\n<ul>\n<li><code>VPS_HOST<\/code> \u2013 DCHost VPS IP adresiniz veya hostname.<\/li>\n<li><code>VPS_USER<\/code> \u2013 \u00d6rne\u011fin <code>deploy<\/code> kullan\u0131c\u0131s\u0131.<\/li>\n<li><code>SSH_PRIVATE_KEY<\/code> \u2013 Deploy i\u00e7in kullan\u0131lacak \u00f6zel SSH anahtar\u0131.<\/li>\n<li><code>APP_PATH<\/code> \u2013 \u00d6rne\u011fin <code>\/var\/www\/myapp<\/code>.<\/li>\n<\/ul>\n<p>Daha ileri seviye gizli y\u00f6netimini, <a href=\"https:\/\/www.dchost.com\/blog\/vpste-secrets-yonetimi-nasil-tatli-tatli-cozulur-sops-age-gitops-akisi-systemd-ve-rotasyon\/\">VPS\u2019te secrets y\u00f6netimini sops + age ile anlatt\u0131\u011f\u0131m\u0131z yaz\u0131da<\/a> detayl\u0131 inceledik. GitHub Actions taraf\u0131nda da benzer prensipler ge\u00e7erli: gizlileri repoya asla d\u00fcz metin koymuyor, her \u015feyi <strong>secrets<\/strong> \u00fczerinden besliyoruz.<\/p>\n<h2><span id=\"PHP_LaravelSymfony_Icin_Ornek_GitHub_Actions_Workflow\">PHP (Laravel\/Symfony) \u0130\u00e7in \u00d6rnek GitHub Actions Workflow<\/span><\/h2>\n<p>\u015eimdi somut bir \u00f6rnek \u00fczerinden gidelim. Laravel tabanl\u0131 bir PHP uygulamas\u0131n\u0131 DCHost VPS\u2019e otomatik ve neredeyse kesintisiz deploy eden basit ama i\u015f g\u00f6ren bir YAML yazal\u0131m.<\/p>\n<h3><span id=\"1_Build_ve_Test_Asamasi\">1. Build ve Test A\u015famas\u0131<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">name: Deploy PHP App to VPS\n\non:\n  push:\n    branches:\n      - main\n\njobs:\n  build-and-deploy:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Kodu \u00e7ek\n        uses: actions\/checkout@v4\n\n      - name: PHP kur\n        uses: shivammathur\/setup-php@v2\n        with:\n          php-version: '8.2'\n          extensions: mbstring, intl, pdo_mysql\n\n      - name: Composer cache\n        uses: actions\/cache@v4\n        with:\n          path: vendor\n          key: ${{ runner.os }}-composer-${{ hashFiles('**\/composer.lock') }}\n\n      - name: Composer install\n        run: composer install --no-dev --prefer-dist --no-interaction --optimize-autoloader\n\n      - name: Testleri \u00e7al\u0131\u015ft\u0131r\n        run: |\n          php artisan test || vendor\/bin\/phpunit || echo &quot;Test komutu uyarlanmal\u0131&quot;\n<\/code><\/pre>\n<p>Buraya kadar olan k\u0131s\u0131m tamamen GitHub runner \u00fczerinde ger\u00e7ekle\u015fiyor. Canl\u0131 sunucuya dokunmadan \u00f6nce kodun derlenip test edilmesini sa\u011fl\u0131yoruz.<\/p>\n<h3><span id=\"2_Build_Ciktisini_Paketleyip_VPSe_Gondermek\">2. Build \u00c7\u0131kt\u0131s\u0131n\u0131 Paketleyip VPS\u2019e G\u00f6ndermek<\/span><\/h3>\n<p>\u015eimdi s\u0131rada artefact\u2019i (uygulama \u00e7\u0131kt\u0131s\u0131n\u0131) VPS\u2019e aktarmak ve orada yeni bir s\u00fcr\u00fcm klas\u00f6r\u00fc olu\u015fturmak var.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">      - name: SSH anahtar\u0131n\u0131 ayarla\n        run: |\n          mkdir -p ~\/.ssh\n          echo &quot;${{ secrets.SSH_PRIVATE_KEY }}&quot; &gt; ~\/.ssh\/id_rsa\n          chmod 600 ~\/.ssh\/id_rsa\n          ssh-keyscan -H ${{ secrets.VPS_HOST }} &gt;&gt; ~\/.ssh\/known_hosts\n\n      - name: Release klas\u00f6r\u00fc ad\u0131n\u0131 olu\u015ftur\n        id: vars\n        run: echo &quot;RELEASE_DIR=$(date +%Y%m%d%H%M%S)&quot; &gt;&gt; $GITHUB_OUTPUT\n\n      - name: Projeyi ar\u015fivle\n        run: |\n          tar czf release.tgz .\n\n      - name: Ar\u015fivi VPS'e g\u00f6nder\n        run: |\n          scp release.tgz ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }}:\/tmp\/release_${{ steps.vars.outputs.RELEASE_DIR }}.tgz\n<\/code><\/pre>\n<h3><span id=\"3_Sunucu_Uzerinde_Yeni_Surumu_Hazirlamak\">3. Sunucu \u00dczerinde Yeni S\u00fcr\u00fcm\u00fc Haz\u0131rlamak<\/span><\/h3>\n<p>\u015eimdi en kritik k\u0131s\u0131mday\u0131z. SSH ile VPS\u2019e ba\u011flan\u0131p yeni <code>release<\/code> klas\u00f6r\u00fcn\u00fc olu\u015fturaca\u011f\u0131z.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">      - name: VPS \u00fczerinde release'i haz\u0131rla\n        run: |\n          ssh ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} &lt;&lt; 'EOF'\n          set -e\n\n          APP_PATH=&quot;${{ secrets.APP_PATH }}&quot;\n          RELEASE_DIR=&quot;${{ steps.vars.outputs.RELEASE_DIR }}&quot;\n\n          mkdir -p &quot;$APP_PATH\/releases\/$RELEASE_DIR&quot;\n          tar xzf &quot;\/tmp\/release_${RELEASE_DIR}.tgz&quot; -C &quot;$APP_PATH\/releases\/$RELEASE_DIR&quot;\n          rm &quot;\/tmp\/release_${RELEASE_DIR}.tgz&quot;\n\n          # shared .env ve storage'i ba\u011fla\n          ln -nfs &quot;$APP_PATH\/shared\/.env&quot; &quot;$APP_PATH\/releases\/$RELEASE_DIR\/.env&quot;\n          mkdir -p &quot;$APP_PATH\/shared\/storage&quot;\n          rm -rf &quot;$APP_PATH\/releases\/$RELEASE_DIR\/storage&quot;\n          ln -nfs &quot;$APP_PATH\/shared\/storage&quot; &quot;$APP_PATH\/releases\/$RELEASE_DIR\/storage&quot;\n\n          cd &quot;$APP_PATH\/releases\/$RELEASE_DIR&quot;\n          composer install --no-dev --prefer-dist --no-interaction --optimize-autoloader\n          php artisan config:cache || true\n          php artisan route:cache || true\n          php artisan view:cache || true\n          php artisan migrate --force || true\n\n          # current symlink'ini atomik olarak g\u00fcncelle\n          ln -nfs &quot;$APP_PATH\/releases\/$RELEASE_DIR&quot; &quot;$APP_PATH\/current_new&quot;\n          mv -fT &quot;$APP_PATH\/current_new&quot; &quot;$APP_PATH\/current&quot;\n\n          # PHP-FPM reload\n          sudo systemctl reload php8.2-fpm || sudo systemctl reload php-fpm\n\n          # Eski release'leri temizle (son 5'i b\u0131rak)\n          cd &quot;$APP_PATH\/releases&quot;\n          ls -1t | tail -n +6 | xargs -r rm -rf\n          EOF\n<\/code><\/pre>\n<p>Burada <code>ln -nfs<\/code> ve <code>mv -fT<\/code> kullan\u0131m\u0131 sayesinde, <code>current<\/code> symlink\u2019inin g\u00fcncellenmesi <strong>atomik<\/strong> ger\u00e7ekle\u015fiyor. Yani Nginx\/PHP-FPM, bir anda eski s\u00fcr\u00fcmden yeni s\u00fcr\u00fcme ge\u00e7iyor; arada bozuk bir durum g\u00f6rm\u00fcyor. Veritaban\u0131 migration\u2019lar\u0131n\u0131 da deploy s\u00fcrecine entegre etti\u011finiz i\u00e7in, kod ve \u015fema birlikte g\u00fcncelleniyor.<\/p>\n<h2><span id=\"Nodejs_Icin_ZeroDowntime_GitHub_Actions_Workflow\">Node.js \u0130\u00e7in Zero\u2011Downtime GitHub Actions Workflow<\/span><\/h2>\n<p>Benzer mant\u0131\u011f\u0131 Node.js uygulamalar\u0131 i\u00e7in de kurabiliriz. \u00d6rne\u011fin Nest.js veya Express tabanl\u0131 bir API\u2019niz olsun; build s\u00fcrecini GitHub Actions\u2019ta yap\u0131p sadece derlenmi\u015f \u00e7\u0131kt\u0131y\u0131 VPS\u2019e g\u00f6ndererek sunucu y\u00fck\u00fcn\u00fc azaltabilirsiniz.<\/p>\n<h3><span id=\"1_Build_ve_Test\">1. Build ve Test<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">name: Deploy Node App to VPS\n\non:\n  push:\n    branches:\n      - main\n\njobs:\n  build-and-deploy:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Kodu \u00e7ek\n        uses: actions\/checkout@v4\n\n      - name: Node versiyonunu ayarla\n        uses: actions\/setup-node@v4\n        with:\n          node-version: '20'\n\n      - name: Ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00fckle\n        run: |\n          npm ci\n\n      - name: Testleri \u00e7al\u0131\u015ft\u0131r\n        run: |\n          npm test || echo &quot;Test komutu proje yap\u0131s\u0131na g\u00f6re uyarlanmal\u0131&quot;\n\n      - name: Prod build al\n        run: |\n          npm run build\n<\/code><\/pre>\n<h3><span id=\"2_Build_Ciktisini_Gonderme_ve_Servisi_Yenileme\">2. Build \u00c7\u0131kt\u0131s\u0131n\u0131 G\u00f6nderme ve Servisi Yenileme<\/span><\/h3>\n<p>Burada genellikle <code>dist<\/code> veya <code>.next<\/code> gibi derlenmi\u015f klas\u00f6r\u00fc, bir <code>release<\/code> klas\u00f6r\u00fc i\u00e7ine kopyalay\u0131p symlink\u2019i kayd\u0131r\u0131yoruz.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">      - name: SSH anahtar\u0131n\u0131 ayarla\n        run: |\n          mkdir -p ~\/.ssh\n          echo &quot;${{ secrets.SSH_PRIVATE_KEY }}&quot; &gt; ~\/.ssh\/id_rsa\n          chmod 600 ~\/.ssh\/id_rsa\n          ssh-keyscan -H ${{ secrets.VPS_HOST }} &gt;&gt; ~\/.ssh\/known_hosts\n\n      - name: Release klas\u00f6r\u00fc ad\u0131n\u0131 olu\u015ftur\n        id: vars\n        run: echo &quot;RELEASE_DIR=$(date +%Y%m%d%H%M%S)&quot; &gt;&gt; $GITHUB_OUTPUT\n\n      - name: Sadece gerekli dosyalar\u0131 ar\u015fivle\n        run: |\n          tar czf node_release.tgz package.json package-lock.json dist\n\n      - name: Ar\u015fivi VPS'e g\u00f6nder\n        run: |\n          scp node_release.tgz ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }}:\/tmp\/node_release_${{ steps.vars.outputs.RELEASE_DIR }}.tgz\n\n      - name: VPS \u00fczerinde Node release'ini haz\u0131rla\n        run: |\n          ssh ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} &lt;&lt; 'EOF'\n          set -e\n\n          APP_PATH=&quot;${{ secrets.APP_PATH }}&quot;\n          RELEASE_DIR=&quot;${{ steps.vars.outputs.RELEASE_DIR }}&quot;\n\n          mkdir -p &quot;$APP_PATH\/releases\/$RELEASE_DIR&quot;\n          tar xzf &quot;\/tmp\/node_release_${RELEASE_DIR}.tgz&quot; -C &quot;$APP_PATH\/releases\/$RELEASE_DIR&quot;\n          rm &quot;\/tmp\/node_release_${RELEASE_DIR}.tgz&quot;\n\n          # shared .env'i ba\u011fla\n          ln -nfs &quot;$APP_PATH\/shared\/.env&quot; &quot;$APP_PATH\/releases\/$RELEASE_DIR}\/.env&quot;\n\n          cd &quot;$APP_PATH\/releases\/$RELEASE_DIR&quot;\n          npm ci --omit=dev\n\n          # symlink'i atomik g\u00fcncelle\n          ln -nfs &quot;$APP_PATH\/releases\/$RELEASE_DIR&quot; &quot;$APP_PATH\/current_new&quot;\n          mv -fT &quot;$APP_PATH\/current_new&quot; &quot;$APP_PATH\/current&quot;\n\n          # Node servisini reload et\n          sudo systemctl reload myapp || sudo systemctl restart myapp\n\n          # Eski release'leri temizle\n          cd &quot;$APP_PATH\/releases&quot;\n          ls -1t | tail -n +6 | xargs -r rm -rf\n          EOF\n<\/code><\/pre>\n<p>E\u011fer PM2 kullan\u0131yorsan\u0131z, <code>systemctl reload<\/code> yerine <code>pm2 reload myapp<\/code> benzeri bir komutla zero\u2011downtime restart kurgulayabilirsiniz. Bunun ayr\u0131nt\u0131lar\u0131n\u0131, <a href=\"https:\/\/www.dchost.com\/blog\/node-jsi-canliya-alirken-panik-yapma-pm2-systemd-nginx-ssl-ve-sifir-kesinti-deploy-nasil-kurulur\/\">PM2 ve systemd ile Node.js\u2019i s\u0131f\u0131r kesintiyle yay\u0131nlama rehberimizde<\/a> ad\u0131m ad\u0131m anlatt\u0131k.<\/p>\n<h2><span id=\"Rollback_BlueGreen_ve_Canary_Isler_Sarpa_Sarinca_Ne_Yapacagiz\">Rollback, Blue\u2011Green ve Canary: \u0130\u015fler Sarpa Sar\u0131nca Ne Yapaca\u011f\u0131z?<\/span><\/h2>\n<p>Hi\u00e7bir deploy s\u00fcreci %100 hatas\u0131z de\u011fildir. \u00d6nemli olan, bir problem \u00e7\u0131kt\u0131\u011f\u0131nda ne kadar h\u0131zl\u0131 geri d\u00f6nebilece\u011finizdir. Sembolik <code>current<\/code> stratejisi bu y\u00fczden \u00e7ok g\u00fc\u00e7l\u00fc.<\/p>\n<h3><span id=\"Basit_Rollback_Stratejisi\">Basit Rollback Stratejisi<\/span><\/h3>\n<p>Sunucuda \u015fu komutla son 5 release\u2019i g\u00f6rebilirsiniz:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">cd \/var\/www\/myapp\/releases\nls -1t\n<\/code><\/pre>\n<p>\u00d6rne\u011fin en yeni s\u00fcr\u00fcm hatal\u0131ysa, bir \u00f6nceki klas\u00f6re d\u00f6nmek i\u00e7in:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">PREV=$(ls -1t | sed -n '2p')\nln -nfs &quot;\/var\/www\/myapp\/releases\/$PREV&quot; &quot;\/var\/www\/myapp\/current_new&quot;\nmv -fT &quot;\/var\/www\/myapp\/current_new&quot; &quot;\/var\/www\/myapp\/current&quot;\n\n# PHP veya Node servisini reload et\nsudo systemctl reload php8.2-fpm || sudo systemctl reload myapp\n<\/code><\/pre>\n<p>Daha geli\u015fmi\u015f senaryolarda, Nginx a\u011f\u0131rl\u0131kl\u0131 y\u00f6nlendirme ve sa\u011fl\u0131k kontrol\u00fc ile canary da\u011f\u0131t\u0131m yapmak da m\u00fcmk\u00fcn. Bu konsepte ilgi duyuyorsan\u0131z, <a href=\"https:\/\/www.dchost.com\/blog\/vpste-canary-dagitimi-nasil-tatli-tatli-kurulur-nginx-agirlikli-yonlendirme-saglik-kontrolu-ve-guvenli-rollback\/\">VPS\u2019te canary da\u011f\u0131t\u0131m\u0131n\u0131 Nginx ve health check ile anlatt\u0131\u011f\u0131m\u0131z rehbere<\/a> g\u00f6z atabilirsiniz.<\/p>\n<h2><span id=\"CICD_Surecini_Destekleyen_Ek_Adimlar_Git_Load_Test_ve_Izleme\">CI\/CD S\u00fcrecini Destekleyen Ek Ad\u0131mlar: Git, Load Test ve \u0130zleme<\/span><\/h2>\n<p>Otomatik deploy sadece \u201ckod gitsin\u201d demek de\u011fildir; ekosistemi b\u00fct\u00fcn olarak d\u00fc\u015f\u00fcnmek gerekir.<\/p>\n<h3><span id=\"Git_ile_Otomatik_Deploy_Kulturu\">Git ile Otomatik Deploy K\u00fclt\u00fcr\u00fc<\/span><\/h3>\n<p>Ekipler genellikle \u00f6nce <a href=\"https:\/\/www.dchost.com\/blog\/git-ile-otomatik-deploy-cpanel-plesk-ve-vpste-adim-adim-kurulum\/\">Git ile otomatik deploy\u2019un temellerini<\/a> \u00f6\u011freniyor, ard\u0131ndan bunu GitHub Actions gibi CI\/CD sistemleriyle peki\u015ftiriyor. \u00d6nemli olan; canl\u0131 ortama eri\u015fimi, do\u011frudan SSH a\u00e7mak yerine <strong>pull request + merge + pipeline<\/strong> \u00fc\u00e7l\u00fcs\u00fcne ba\u011flamak.<\/p>\n<h3><span id=\"Yuk_Testi_ve_Kapasite_Analizi\">Y\u00fck Testi ve Kapasite Analizi<\/span><\/h3>\n<p>Yeni bir \u00f6zellik deploy etti\u011finizde, sadece &#8220;\u00e7al\u0131\u015f\u0131yor mu&#8221; de\u011fil, &#8220;y\u00fck alt\u0131nda nas\u0131l davran\u0131yor&#8221; sorusunu da yan\u0131tlaman\u0131z gerekir. Bunu, <a href=\"https:\/\/www.dchost.com\/blog\/trafik-patlamasindan-once-load-test-yapmak-k6-jmeter-ve-locust-ile-kapasite-olcme-rehberi\/\">k6, JMeter ve Locust ile load test yapmay\u0131 anlatt\u0131\u011f\u0131m\u0131z rehberde<\/a> detayl\u0131 i\u015fledik. CI\/CD hatt\u0131n\u0131za basit y\u00fck testlerini entegre ederek, problemli performans de\u011fi\u015fikliklerini canl\u0131ya \u00e7\u0131kmadan yakalayabilirsiniz.<\/p>\n<h2><span id=\"DCHost_Uzerinde_Ornek_Senaryo_PHP_API_Nodejs_Frontend\">DCHost \u00dczerinde \u00d6rnek Senaryo: PHP API + Node.js Frontend<\/span><\/h2>\n<p>Ger\u00e7ek bir projeden kolayca t\u00fcretilebilecek bir senaryo \u00fczerinden d\u00fc\u015f\u00fcnelim. DCHost \u00fczerinde 4 vCPU, 8 GB RAM ve NVMe diskli bir VPS\u2019iniz var. Ayn\u0131 sunucuda:<\/p>\n<ul>\n<li>Laravel tabanl\u0131 bir API (PHP 8.2, Nginx + PHP-FPM),<\/li>\n<li>Next.js tabanl\u0131 bir frontend (Node 20, Nginx reverse proxy),<\/li>\n<li>Redis ve MariaDB gibi ek servisler<\/li>\n<\/ul>\n<p>\u00e7al\u0131\u015f\u0131yor olsun.<\/p>\n<p>Bu projeyi \u015fu \u015fekilde kurgulayabilirsiniz:<\/p>\n<ul>\n<li>Tek GitHub monorepo; <code>api\/<\/code> ve <code>frontend\/<\/code> klas\u00f6rleri.<\/li>\n<li>\u0130ki ayr\u0131 GitHub Actions workflow: <code>deploy-api.yml<\/code> ve <code>deploy-frontend.yml<\/code>.<\/li>\n<li>VPS \u00fczerinde iki ayr\u0131 <code>APP_PATH<\/code>: <code>\/var\/www\/api<\/code> ve <code>\/var\/www\/frontend<\/code>.<\/li>\n<li>Nginx siteleri, ilgili <code>current<\/code> klas\u00f6rlerine bakacak \u015fekilde ayarl\u0131.<\/li>\n<\/ul>\n<p>Her push\u2019ta:<\/p>\n<ul>\n<li><code>api\/<\/code> alt\u0131ndaki de\u011fi\u015fiklikler varsa PHP workflow\u2019u tetiklenir ve sadece API deploy edilir.<\/li>\n<li><code>frontend\/<\/code> alt\u0131ndaki de\u011fi\u015fiklikler varsa Node workflow\u2019u tetiklenir ve sadece frontend deploy edilir.<\/li>\n<\/ul>\n<p>B\u00f6ylece tek VPS \u00fczerinde hem PHP hem de Node.js d\u00fcnyas\u0131n\u0131, GitHub Actions ile disiplinli ve zero\u2011downtime\u2019a \u00e7ok yak\u0131n \u015fekilde y\u00f6netmi\u015f olursunuz. Trafik ve kaynak ihtiyac\u0131n\u0131z artt\u0131\u011f\u0131nda, ayn\u0131 mimariyi DCHost \u00fczerinde ek VPS\u2019ler veya <a href=\"https:\/\/www.dchost.com\/tr\/fiziksel-sunucu\">dedicated sunucu<\/a>lar ile yatayda geni\u015fletebilirsiniz.<\/p>\n<h2><span id=\"Sonuc_ve_Sonraki_Adimlar_Kucuk_Bir_YAML_Buyuk_Bir_Rahatlik\">Sonu\u00e7 ve Sonraki Ad\u0131mlar: K\u00fc\u00e7\u00fck Bir YAML, B\u00fcy\u00fck Bir Rahatl\u0131k<\/span><\/h2>\n<p>Manuel deploy s\u00fcre\u00e7leri, k\u0131sa vadede \u201ckolaym\u0131\u015f\u201d gibi hissettirse de, orta vadede hataya a\u00e7\u0131k, takip edilemez ve ekip b\u00fcy\u00fcd\u00fck\u00e7e s\u00fcrd\u00fcr\u00fclemez hale geliyor. GitHub Actions ile VPS\u2019e otomatik deploy kurdu\u011funuzda:<\/p>\n<ul>\n<li>Her de\u011fi\u015fiklik, testlerden ge\u00e7mi\u015f ve kay\u0131t alt\u0131na al\u0131nm\u0131\u015f \u015fekilde canl\u0131ya gider.<\/li>\n<li>Zero\u2011downtime\u2019a yak\u0131n yay\u0131n sayesinde kullan\u0131c\u0131lar\u0131n\u0131z deploy anlar\u0131n\u0131 fark etmez.<\/li>\n<li>Rollback, birka\u00e7 komutla veya k\u00fc\u00e7\u00fck bir script ile saniyeler i\u00e7inde m\u00fcmk\u00fcn hale gelir.<\/li>\n<li>Sunucu taraf\u0131nda \u201ckim, ne zaman, ne kopyalad\u0131\u201d sorusu tarihe kar\u0131\u015f\u0131r.<\/li>\n<\/ul>\n<p>DCHost ekibi olarak, ister PHP ister Node.js olsun, projelerinizi GitHub Actions ile otomatik deploy edecek \u015fekilde kurgulaman\u0131za yard\u0131mc\u0131 olacak altyap\u0131y\u0131 ve tecr\u00fcbeyi sunuyoruz. \u0130htiyac\u0131n\u0131za g\u00f6re tek VPS, \u00e7oklu VPS veya dedicated sunucu mimarilerini birlikte planlayabilir; CI\/CD hatt\u0131n\u0131z\u0131 g\u00fcvenlik, performans ve yedeklilik kriterleriyle birlikte tasarlayabiliriz.<\/p>\n<p>Elinizdeki projeyi GitHub Actions ile otomatik deploy\u2019a ta\u015f\u0131mak istiyorsan\u0131z, k\u00fc\u00e7\u00fckten ba\u015flay\u0131n: \u00d6nce staging ortam\u0131 i\u00e7in basit bir workflow kurun, ard\u0131ndan zero\u2011downtime ve rollback ad\u0131mlar\u0131n\u0131 ekleyin. Bu rehberdeki \u00f6rnekleri kendi projenize uyarlay\u0131n, ihtiya\u00e7 duydu\u011funuz noktada da DCHost ekibiyle ileti\u015fime ge\u00e7ip altyap\u0131 taraf\u0131n\u0131 birlikte netle\u015ftirelim.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>\u0130&ccedil;indekiler1 GitHub Actions ile VPS Deploy Neden Bu Kadar Kritik Hale Geldi?2 Genel Mimari: GitHub Actions \u2192 VPS Ak\u0131\u015f\u0131 Nas\u0131l Kurulur?2.1 Branch Stratejisi ve Ortamlar2.2 G\u00fcvenlik Perspektifi: SSH Anahtar\u0131 ve Deploy Kullan\u0131c\u0131s\u01313 VPS Taraf\u0131 Haz\u0131rl\u0131\u011f\u0131: Dizin Yap\u0131s\u0131, systemd ve Nginx\/PHP-FPM3.1 Standart Dizin Yap\u0131s\u01313.2 PHP Uygulamas\u0131 \u0130\u00e7in \u00d6rnek Nginx Konfig\u00fcrasyonu3.3 Node.js Uygulamas\u0131 \u0130\u00e7in systemd Servisi4 GitHub [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3648,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-3647","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/posts\/3647","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/comments?post=3647"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/posts\/3647\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/media\/3648"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/media?parent=3647"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/categories?post=3647"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/tags?post=3647"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}