Menggunakan VirtualDocumentRoot * hanya * jika ada root dokumen yang sesuai


8

Saya ingin mengatur lingkungan tempat host virtual Apache dapat dibuat secara dinamis tanpa memuat ulang konfigurasi.

Saya dapat melakukan ini dengan mod_vhost_alias , saya mengatur virtual host default saya seperti ini

<VirtualHost *>
  UseCanonicalName Off
  VirtualDocumentRoot /var/www/sandboxes/domains/%0
  ServerName catchall.host
</VirtualHost>

Itu berfungsi dengan baik, tetapi jika permintaan dibuat untuk nama host yang saat ini tidak diatur, saya mendapatkan kesalahan 404 Tidak Ditemukan.

Apa yang saya benar - benar ingin lakukan adalah hanya memiliki tendangan VirtualHost ini hanya jika root dokumen ada, jika tidak cobalah untuk mencocokkan vhost lain (dengan kata lain, membuat kehadiran VirtualDocumentRoot bekerja dengan cara yang sama seperti menggunakan ServerAlias)

Saya mencoba membuat ini vhost kedua, dengan vhost pertama hanya menangani semua permintaan, tetapi ini tidak berhasil - permintaan untuk domain di mana VirtualDocumentRoot dikonfigurasi sedang jatuh ke vhost default.

Jadi, bagaimana saya bisa mengkonfigurasi vhost secara dinamis, tetapi dengan fallback ke vhost lain untuk yang belum terkonfigurasi?

Jawaban:


7

Saya menemukan solusi yang bekerja untuk saya.

Saya bisa menggunakan ErrorDocument untuk mengambil 404 Error dalam skrip PHP. Pada awalnya, itu tampak bermasalah. Jika tidak ada DocumentRoot, di mana skrip akan hidup?

Saya bisa menggunakan URL untuk pesan kesalahan, disajikan dari domain yang berbeda. Namun, dalam pengujian saya tidak menemukan cara untuk mengetahui apa domain yang awalnya diminta.

Jawabannya adalah untuk Alias direktori dan melayani kesalahan dari itu, jadi vhost saya terlihat seperti ini

<VirtualHost *>
  UseCanonicalName Off
  VirtualDocumentRoot /var/www/sandboxes/domains/%0
  ServerName catchall.host
  Alias /errors /var/www/default/errors/
  ErrorDocument 404 /errors/notfound.php
</VirtualHost>

Sekarang, ketika sebuah domain yang belum dikonfigurasi diminta, skrip di /var/www/default/errors/notfound.php sebagai gantinya dipanggil. Skrip ini dapat memeriksa $ _SERVER ['HTTP_HOST'] untuk melihat domain apa yang diminta. Jika sebenarnya dikonfigurasi, maka kami memiliki 404 biasa. Jika tidak dikonfigurasi, kami dapat menampilkan beberapa pesan kesalahan alternatif. Dalam kasus saya, ini adalah tempat saya menunjukkan UI untuk membantu mengatur vhost.


Bukankah itu melempar 404 sebagai status untuk setiap permintaan ke default?
Kyle

1
Penangan kesalahan hanya dipanggil jika VirtualDocumentRoot tidak ada (atau benar-benar 404, tetapi notfound.php dapat dengan mudah membedakannya).
Paul Dixon

3

Saya menemukan pertanyaan Anda saat Googling. Saya memiliki masalah yang persis sama dan menerapkan perbaikan seperti yang dijelaskan dalam jawaban Paul . Namun, untuk aplikasi web saya yang kompleks, saya tidak senang dengan merutekan semua permintaan melalui satu notfound.php.

Pada akhirnya, saya berhasil memperbaiki masalah tanpa skrip eksternal, hanya dengan mengedit konfigurasi VirtualHost saya.

Pada awalnya, VirtualHost saya dikonfigurasi seperti ini:

<VirtualHost *:80>
    Usecanonicalname Off
    Virtualdocumentroot /mnt/ramdisk/www/cms-%-3.0-development/
</VirtualHost>

Saya punya URL seperti client1.domainname.com, client2.domainname.comdanwhatever.domainname.com

yang diselesaikan ke /mnt/ramdisk/www/cms-client1-development/, /mnt/ramdisk/www/cms-client2-development/dan/mnt/ramdisk/www/cms-whatever-development/

Namun, URL seperti nonexistent.domainname.comakan memberi saya 404 karena direktori /mnt/ramdisk/www/cms-nonexistent-development/tidak ada. Saya ingin subdomain ini menggunakan direktori/mnt/ramdisk/www/cms-default-development/

Saya memperbaikinya dengan menggunakan ModRewritedan ModProxy:

<VirtualHost *:80>
    Usecanonicalname Off
    Virtualdocumentroot /mnt/ramdisk/www/cms-%-3.0-development/
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^(.*)\.domainname\.com$ [NC]
    RewriteCond /mnt/ramdisk/www/cms-%1-development/ !-d
    RewriteRule (.*) http://default.domainname.com/$1 [P,L]
</VirtualHost>

Apa yang dilakukan adalah: ambil subdomain (bagian sebelumnya .domainname.com), masukkan itu ke path (% 1) dan permintaan proxy ke URL default hanya jika direktori tidak ada.

Dengan menggunakan proxy, prosesnya transparan dan pengguna berpikir dia mengunjungi http://nonexistent.domainname.com , sementara dia benar-benar melihat konten dari http://default.domainname.com/ .


3

Saya juga menemukan pertanyaan ini googling untuk mundur vhost apache2 dinamis dan jawaban Luc banyak membantu saya dengan memecahkan masalah saya, tetapi saya masih ingin menunjukkan apa yang saya lakukan untuk mencapai tujuan saya, terutama karena itu melibatkan beberapa pekerjaan tambahan dan karena saya pikir itu dapat bermanfaat untuk semua googler masa depan ...

Tujuan saya

  • vhosting dinamis untuk semua domain dan subdomain yang menunjuk ke VPS saya
  • foo.com harus menyajikan konten yang sama dengan www.foo.com
  • fallback untuk domain yang tidak dikenal ke semacam default
  • fallback untuk subdomain yang tidak dikenal foo.comke www.foo.comkecuali jika wwwtidak tersedia, fallback ke default sebagai gantinya

DNS

Saya memiliki beberapa domain (dan semua subdomain mereka) yang menunjuk ke VPS saya, misalnya:

  • foo.com
  • bar.com
  • foobar.com

Berkas sistem

Saya memiliki direktori berikut, domain berisi direktori dengan nama-nama subdomain yang tersedia, direktori www diperlukan, tetapi konfigurasi harus dapat menangani situasi di mana itu tidak ada. Localhost digunakan sebagai fallback default:

/var
  /www
    /localhost
    /foo.com
       /www
       /bar
    /bar.com
       /foo

Tes

Menerjemahkan tujuan saya ke dalam kasus yang dapat diuji:

  • foo.com harus dilayani dari foo.com/www
  • www.foo.com harus dilayani dari foo.com/www
  • bar.foo.com harus dilayani dari foo.com/bar
  • foo.foo.com harus dilayani dari foo.com/www (foo.com/foo tidak ada)
  • bar.com harus dilayani dari localhost (bar.com/www tidak ada)
  • www.bar.com harus dilayani dari localhost (bar.com/www tidak ada)
  • foo.bar.com harus dilayani dari bar.com/foo
  • bar.bar.com harus dilayani dari localhost (bar.com/bar tidak ada)
  • foobar.com harus dilayani dari localhost (foobar.com tidak ada)
  • www.foobar.com harus dilayani dari localhost (foobar.com tidak ada)
  • foo.foobar.com harus dilayani dari localhost (foobar.com tidak ada)

Solusinya

Kegunaan ini: mod_rewrite, mod_proxy_httpdan ofcourse mod_vhost_alias.

ServerName my.domain
ServerAdmin admin@my.domain

<VirtualHost *:80>
    ServerName localhost
    VirtualDocumentRoot /var/www/localhost
</VirtualHost>

<VirtualHost *:80>
    ServerName sub.domain
    ServerAlias *.*.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3

    RewriteEngine on

    RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
    RewriteCond /var/www/%2.%3 !-d
    RewriteRule (.*) http://localhost/$1 [P]

    RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
    RewriteCond /var/www/%2.%3/%1 !-d
    RewriteCond /var/www/%2.%3/www !-d
    RewriteRule (.*) http://localhost/$1 [P]

    RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
    RewriteCond /var/www/%2.%3/%1 !-d
    RewriteRule (.*) http://%2.%3/$1 [P]
</VirtualHost>

<VirtualHost *:80>
    ServerName bare.domain
    ServerAlias *.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/www

    RewriteEngine on

    RewriteCond %{HTTP_HOST} ^(.*)\.(.*)$ [NC]
    RewriteCond /var/www/%1.%2 !-d [OR]
    RewriteCond /var/www/%1.%2/www !-d
    RewriteRule (.*) http://localhost/$1 [P]
</VirtualHost>

Bagaimana cara kerjanya? Ada tiga host virtual yang didefinisikan:

localhost

Localhost berfungsi sebagai default. Semua permintaan yang tidak dapat diselesaikan dilayani oleh localhost. Menyiapkan symlink dari localhost ke salah satu domain Anda seperti mengatur situs itu sebagai default.

sub.domain

Sub.domain vhost menerima semua permintaan dalam bentuk *.*.*. Secara default semua permintaan dilayani dari /domain.com/subseperti yang didefinisikan oleh VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3.

mundur:

Yang pertama RewriteRulemenangani domain yang tidak dikenal, misalnya. domain.comdirektori tidak ada, dengan mem-proxy situs web localhost.

Kedua RewriteRuleproxy juga ke localhost ketika kedua domain.com/subdan domain.com/wwwdirektori yang tidak hadir.

RewriteRuleProxy ketiga domain.comsaat domain.com/subtidak ada. Kita tahu domain.com/wwwada karena blok penulisan ulang kedua.

bare.domain

Bare.domain vhost menerima *.*permintaan dan melayani mereka/domain.com/www

Di sini RewriteRuleproksi akan ke localhost ketika domain.comatau domain.com/wwwtidak ada.

^ $%. * !!!

Saya mengalami kesulitan membungkus kepala saya di sekitar semua itu $dan %tanda - tanda di RewriteConddan RewriteRulejadi saya akan menjelaskan tentang mereka di sini:

    ServerAlias *.*.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3
    RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC]
    RewriteCond /var/www/%2.%3/%1 !-d
    RewriteRule (.*) http://%2.%3/$1 [P]
  • Di *dalam ServerAliashanya wildcard.
  • Di %ndalam VirtualDocumentRootberasal dari interpolasi nama dokumen .
  • The %nin the second RewriteCondmerujuk pada pilihan (.*)dari yang pertama RewriteCond, mis. bagian dari domain yang diminta.
  • The %ndalam RewriteRulemelakukan terlalu.
  • The $1dalam RewriteRulemengacu pada seleksi (.*)di awal RewriteRule. Yang menangkap semuanya dari domain hingga ?di url permintaan. Pertanyaan apa pun secara otomatis ditambahkan ke url oleh mod_proxy.

1

Hanya membuangnya di sana, saya mendapatkan hasil yang sama (minus redirect localhost) seperti RemyNL, tetapi juga termasuk alamat IP saat menghubungkan langsung:

<VirtualHost _default_:80>
    RewriteEngine On
    RewriteCond %{HTTPS} Off [OR] 
    RewriteCond %{HTTP:X-Forwarded-Proto} !https
    RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R=301,L]
</VirtualHost>

<VirtualHost _default_:443>
    ServerName a.b.c.d
    ServerAlias *.*.*.*
    VirtualDocumentRoot /var/www/%0
</VirtualHost>

<VirtualHost _default_:443>
    ServerName a.b.c
    ServerAlias *.*.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3
</VirtualHost>

<VirtualHost _default_:443>
    ServerName a.b
    ServerAlias *.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/www
</VirtualHost>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.