The structure looks like this:
|-storage
| |-site1
| | |-cache
| | |-content
| | |-sessions
| | |-accounts
| | |-media
| | | |-panel
| | | |-plugins
| | | |-compiled
| | | | |-styles.css
| | | |-site
| | | | |-b32c5ffa87-1723583028
| | | | | |-.jobs
| | | | | | |-logotellieblack-76x.png.json
| | | | | | |-logotellieblack-38x.png.json
| | | | | | |-logotellieblack-960x-q90.webp.json
| | | | |-fc03371610-1723582877
| | | | | |-.jobs
| | | | | | |-logotelliewhite-352x.png.json
| | | | | | |-logotelliewhite-864x.png.json
| | | | | | |-logotelliewhite-76x.png.json
| | | | | | |-logotelliewhite-960x-q90.webp.json
| | | | | | |-logotelliewhite-1408x.png.json
| | | | | | |-logotelliewhite-38x.png.json
|-sites
| |-sites.txt
| |-site1
| | |-snippets
| | | |-modules
| | |-blueprints
| | | |-site.yml
| | | |-modules
| | | |-pages
| | |-css
| | |-config
| | | |-config.php
| | |-languages
| | |-templates
| | |-assets
|-public
| |-index.php
| |-.htaccess
|-global
| |-plugins
The files are divided in two categories, one category for the site-specific files like blueprints, templates, snippets, config and so on; and the other category with the storage files which need to be persisted, like content, sessions, cache, media etc.
The plugins are all the same for every site, therefore they live in a global directory.
The index.php looks like this:
$site = "site1"; // this will be set through a mapping table from the host name in the request
$storage = realpath(__DIR__ . '/../storage/' . $site);
$roots = [
'index' => __DIR__,
'site' => realpath(__DIR__ . '/../sites/' . $root),
'plugins' => realpath(__DIR__ . '/../global/plugins'),
'storage' => $storage,
'content' => $storage . '/content',
'accounts' => $storage . '/accounts',
'cache' => $storage . '/cache',
'sessions' => $storage . '/sessions',
'media' => $storage . '/media',
];
Output of command dump(kirby()->roots());
:
Kirby\Cms\Ingredients Object
(
[kirby] => /var/www/kirby
[i18n] => /var/www/kirby/i18n
[i18n:translations] => /var/www/kirby/i18n/translations
[i18n:rules] => /var/www/kirby/i18n/rules
[index] => /var/www/public
[assets] => /var/www/public/assets
[content] => /var/www/storage/site1/content
[media] => /var/www/storage/site1/media
[panel] => /var/www/kirby/panel
[site] => /var/www/sites/site1
[accounts] => /var/www/storage/site1/accounts
[blueprints] => /var/www/sites/site1/blueprints
[cache] => /var/www/storage/site1/cache
[collections] => /var/www/sites/site1/collections
[commands] => /var/www/sites/site1/commands
[config] => /var/www/sites/site1/config
[controllers] => /var/www/sites/site1/controllers
[languages] => /var/www/sites/site1/languages
[license] => /var/www/sites/site1/config/.license
[logs] => /var/www/sites/site1/logs
[models] => /var/www/sites/site1/models
[plugins] => /var/www/global/plugins
[sessions] => /var/www/storage/site1/sessions
[snippets] => /var/www/sites/site1/snippets
[templates] => /var/www/sites/site1/templates
[roles] => /var/www/sites/site1/blueprints/users
[storage] => /var/www/storage/site1
)
media files made accessible through Apache rewrite rules:
RewriteMap dynamicmap txt:/var/www/sites/sites.txt
# RewriteEngine einschalten
RewriteEngine On
# Entferne die Portnummer aus dem Hostnamen, falls vorhanden
RewriteCond %{HTTP_HOST} ^([^:]+)
RewriteRule ^ - [E=HOST_WITHOUT_PORT:%1]
RewriteCond %{REQUEST_URI} !^/media/plugins
RewriteCond ${dynamicmap:%{ENV:HOST_WITHOUT_PORT}} ^(.+)$
RewriteRule ^/media/(.*)$ ${APACHE_DOCUMENT_ROOT}/../storage/%1/media/$1 [L]
RewriteCond ${dynamicmap:%{ENV:HOST_WITHOUT_PORT}} ^(.+)$
RewriteRule ^/assets/(.*)$ ${APACHE_DOCUMENT_ROOT}/../sites/%1/assets/$1 [L]
Like said before the rest of the media files work fine, for example the auto-generated panel files. It’s only the uploaded images in the panel which don’t work.
Hopefully that helps.