diff --git a/CHANGELOG.md b/CHANGELOG.md index 98d082de6..2d528ab22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,11 @@ release channel, you can take advantage of these new features and fixes. subdomains; this is useful for self-hosted services like MinIO or other services that rely on subdirectories instead of subdomains. +- We have changed the mapping for many persistent items in our Docker filesystem to map to folders + within `/var/azuracast/storage`. To preserve back-compatibility, for most users we will continue to map the individual + folders within that as separate volumes, but if you manually manage your volume mounts, you can now just mount a + volume at `/var/azuracast/storage` instead of each of the separate subfolders. + ## Bug Fixes - For stations using the AutoDJ to broadcast, the threshold for what counts as "Station Offline" has been changed, which diff --git a/docker-compose.sample.yml b/docker-compose.sample.yml index 7d5093424..3e5d3b21b 100644 --- a/docker-compose.sample.yml +++ b/docker-compose.sample.yml @@ -181,15 +181,15 @@ services: PUID: ${AZURACAST_PUID:-1000} PGID: ${AZURACAST_PGID:-1000} volumes: - - www_uploads:/var/azuracast/uploads - station_data:/var/azuracast/stations - - shoutcast2_install:/var/azuracast/servers/shoutcast2 - - stereo_tool_install:/var/azuracast/servers/stereo_tool - - geolite_install:/var/azuracast/geoip - - sftpgo_data:/var/azuracast/sftpgo/persist - backups:/var/azuracast/backups - - acme:/var/azuracast/acme - db_data:/var/lib/mysql + - www_uploads:/var/azuracast/storage/uploads + - shoutcast2_install:/var/azuracast/storage/shoutcast2 + - stereo_tool_install:/var/azuracast/storage/stereo_tool + - geolite_install:/var/azuracast/storage/geoip + - sftpgo_data:/var/azuracast/storage/sftpgo + - acme:/var/azuracast/storage/acme restart: unless-stopped ulimits: nofile: diff --git a/src/AppFactory.php b/src/AppFactory.php index 6fedf77bc..4d402d2ec 100644 --- a/src/AppFactory.php +++ b/src/AppFactory.php @@ -8,6 +8,7 @@ use App\Console\Application; use App\Enums\SupportedLocales; use App\Http\Factory\ResponseFactory; use App\Http\Factory\ServerRequestFactory; +use App\Utilities\File; use App\Utilities\Logger as AppLogger; use DI; use Monolog\ErrorHandler; @@ -129,7 +130,10 @@ final class AppFactory $environment[Environment::TEMP_DIR] ??= $parentBaseDir . '/www_tmp'; $environment[Environment::CONFIG_DIR] ??= $baseDir . '/config'; $environment[Environment::VIEWS_DIR] ??= $baseDir . '/templates'; - $environment[Environment::UPLOADS_DIR] ??= $parentBaseDir . '/uploads'; + $environment[Environment::UPLOADS_DIR] ??= File::getFirstExistingDirectory([ + $parentBaseDir . '/storage/uploads', + $parentBaseDir . '/uploads', + ]); $_ENV = getenv(); diff --git a/src/Controller/Api/Admin/Shoutcast/PostAction.php b/src/Controller/Api/Admin/Shoutcast/PostAction.php index 00aa6b6d4..9d03e7366 100644 --- a/src/Controller/Api/Admin/Shoutcast/PostAction.php +++ b/src/Controller/Api/Admin/Shoutcast/PostAction.php @@ -4,11 +4,11 @@ declare(strict_types=1); namespace App\Controller\Api\Admin\Shoutcast; -use App\Container\EnvironmentAwareTrait; use App\Controller\SingleActionInterface; use App\Entity\Api\Status; use App\Http\Response; use App\Http\ServerRequest; +use App\Radio\Frontend\Shoutcast; use App\Service\Flow; use Psr\Http\Message\ResponseInterface; use RuntimeException; @@ -16,8 +16,6 @@ use Symfony\Component\Process\Process; final class PostAction implements SingleActionInterface { - use EnvironmentAwareTrait; - public function __invoke( ServerRequest $request, Response $response, @@ -32,8 +30,7 @@ final class PostAction implements SingleActionInterface return $flowResponse; } - $scBaseDir = $this->environment->getParentDirectory() . '/servers/shoutcast2'; - + $scBaseDir = Shoutcast::getDirectory(); $scTgzPath = $scBaseDir . '/sc_serv.tar.gz'; if (is_file($scTgzPath)) { unlink($scTgzPath); diff --git a/src/Radio/Frontend/Shoutcast.php b/src/Radio/Frontend/Shoutcast.php index db56a099d..b59e325a3 100644 --- a/src/Radio/Frontend/Shoutcast.php +++ b/src/Radio/Frontend/Shoutcast.php @@ -6,8 +6,11 @@ namespace App\Radio\Frontend; use App\Entity\Station; use App\Entity\StationMount; +use App\Environment; use App\Service\Acme; +use App\Utilities\File; use GuzzleHttp\Promise\Utils; +use InvalidArgumentException; use NowPlaying\Result\Result; use Psr\Http\Message\UriInterface; use Symfony\Component\Process\Process; @@ -19,10 +22,23 @@ final class Shoutcast extends AbstractFrontend */ public function getBinary(): ?string { - $newPath = '/var/azuracast/servers/shoutcast2/sc_serv'; - return file_exists($newPath) - ? $newPath - : null; + try { + $binaryPath = self::getDirectory() . '/sc_serv'; + return file_exists($binaryPath) + ? $binaryPath + : null; + } catch (InvalidArgumentException) { + return null; + } + } + + public static function getDirectory(): string + { + $parentDir = Environment::getInstance()->getParentDirectory(); + return File::getFirstExistingDirectory([ + $parentDir . '/servers/shoutcast2', + $parentDir . '/storage/shoutcast2', + ]); } public function getVersion(): ?string diff --git a/src/Radio/StereoTool.php b/src/Radio/StereoTool.php index e0105df11..dd775c08c 100644 --- a/src/Radio/StereoTool.php +++ b/src/Radio/StereoTool.php @@ -6,6 +6,7 @@ namespace App\Radio; use App\Entity\Station; use App\Environment; +use App\Utilities\File; final class StereoTool { @@ -21,7 +22,11 @@ final class StereoTool public static function getLibraryPath(): string { - return Environment::getInstance()->getParentDirectory() . '/servers/stereo_tool'; + $parentDir = Environment::getInstance()->getParentDirectory(); + return File::getFirstExistingDirectory([ + $parentDir . '/storage/stereo_tool', + $parentDir . '/servers/stereo_tool', + ]); } public static function isReady(Station $station): bool diff --git a/src/Service/Acme.php b/src/Service/Acme.php index bc847e39d..38192aa0a 100644 --- a/src/Service/Acme.php +++ b/src/Service/Acme.php @@ -13,6 +13,7 @@ use App\Message\AbstractMessage; use App\Message\GenerateAcmeCertificate; use App\Nginx\Nginx; use App\Radio\Adapters; +use App\Utilities\File; use Exception; use Monolog\Handler\StreamHandler; use Psr\Log\LogLevel; @@ -205,7 +206,12 @@ final class Acme public static function getAcmeDirectory(): string { - return Environment::getInstance()->getParentDirectory() . '/acme'; + $parentDir = Environment::getInstance()->getParentDirectory(); + + return File::getFirstExistingDirectory([ + $parentDir . '/acme', + $parentDir . '/storage/acme', + ]); } public static function getCertificatePaths(): array diff --git a/src/Service/IpGeolocator/GeoLite.php b/src/Service/IpGeolocator/GeoLite.php index d804f94ff..a26b048d2 100644 --- a/src/Service/IpGeolocator/GeoLite.php +++ b/src/Service/IpGeolocator/GeoLite.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace App\Service\IpGeolocator; use App\Environment; +use App\Utilities\File; final class GeoLite extends AbstractIpGeolocator { @@ -15,8 +16,12 @@ final class GeoLite extends AbstractIpGeolocator public static function getBaseDirectory(): string { - $environment = Environment::getInstance(); - return dirname($environment->getBaseDirectory()) . '/geoip'; + $parentDir = Environment::getInstance()->getParentDirectory(); + + return File::getFirstExistingDirectory([ + $parentDir . '/geoip', + $parentDir . '/storage/geoip', + ]); } public static function getDatabasePath(): string diff --git a/src/Utilities/File.php b/src/Utilities/File.php index bd970c16a..99e8cbfa0 100644 --- a/src/Utilities/File.php +++ b/src/Utilities/File.php @@ -153,4 +153,26 @@ final class File } } } + + public static function getFirstExistingFile(array $files): string + { + foreach ($files as $file) { + if (file_exists($file)) { + return $file; + } + } + + throw new InvalidArgumentException('No existing files found.'); + } + + public static function getFirstExistingDirectory(array $dirs): string + { + foreach ($dirs as $dir) { + if (is_dir($dir)) { + return $dir; + } + } + + throw new InvalidArgumentException('No existing directories found.'); + } } diff --git a/util/docker/common/add_user.sh b/util/docker/common/add_user.sh index 5851cb4df..1d34da0c5 100644 --- a/util/docker/common/add_user.sh +++ b/util/docker/common/add_user.sh @@ -11,10 +11,14 @@ adduser --home /var/azuracast --disabled-password --gecos "" azuracast usermod -aG www-data azuracast -mkdir -p /var/azuracast/www /var/azuracast/stations /var/azuracast/servers/shoutcast2 \ - /var/azuracast/servers/stereo_tool /var/azuracast/backups /var/azuracast/www_tmp \ - /var/azuracast/uploads /var/azuracast/geoip /var/azuracast/dbip \ - /var/azuracast/acme +mkdir -p /var/azuracast/www /var/azuracast/stations /var/azuracast/www_tmp \ + /var/azuracast/dbip \ + /var/azuracast/storage/uploads \ + /var/azuracast/storage/shoutcast2 \ + /var/azuracast/storage/stereo_tool \ + /var/azuracast/storage/geoip \ + /var/azuracast/storage/sftpgo \ + /var/azuracast/storage/acme chown -R azuracast:azuracast /var/azuracast chmod -R 777 /var/azuracast/www_tmp diff --git a/util/docker/web/sftpgo/sftpgo.json b/util/docker/web/sftpgo/sftpgo.json index 443d3dd95..e8be15c66 100644 --- a/util/docker/web/sftpgo/sftpgo.json +++ b/util/docker/web/sftpgo/sftpgo.json @@ -43,9 +43,9 @@ } ], "host_keys": [ - "persist/id_rsa", - "persist/id_ecdsa", - "persist/id_ed25519" + "../storage/sftpgo/id_rsa", + "../storage/sftpgo/id_ecdsa", + "../storage/sftpgo/id_ed25519" ], "enable_scp": true }, diff --git a/util/docker/web/startup_scripts/03_persist_dir.sh b/util/docker/web/startup_scripts/03_persist_dir.sh new file mode 100644 index 000000000..d6b76099f --- /dev/null +++ b/util/docker/web/startup_scripts/03_persist_dir.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +export DEBIAN_FRONTEND=noninteractive + +echo "Creating persist directories..." + +mkdir -p /var/azuracast/storage/uploads \ + /var/azuracast/storage/shoutcast2 \ + /var/azuracast/storage/stereo_tool \ + /var/azuracast/storage/geoip \ + /var/azuracast/storage/sftpgo \ + /var/azuracast/storage/acme diff --git a/util/docker/web/startup_scripts/07_sftpgo_conf.sh b/util/docker/web/startup_scripts/07_sftpgo_conf.sh index 0cff72767..99e93906f 100644 --- a/util/docker/web/startup_scripts/07_sftpgo_conf.sh +++ b/util/docker/web/startup_scripts/07_sftpgo_conf.sh @@ -1,15 +1,15 @@ #!/bin/bash -if [[ ! -f /var/azuracast/sftpgo/persist/id_rsa ]]; then - ssh-keygen -t rsa -b 4096 -f /var/azuracast/sftpgo/persist/id_rsa -q -N "" +if [[ ! -f /var/azuracast/storage/sftpgo/id_rsa ]]; then + ssh-keygen -t rsa -b 4096 -f /var/azuracast/storage/sftpgo/id_rsa -q -N "" fi -if [[ ! -f /var/azuracast/sftpgo/persist/id_ecdsa ]]; then - ssh-keygen -t ecdsa -b 521 -f /var/azuracast/sftpgo/persist/id_ecdsa -q -N "" +if [[ ! -f /var/azuracast/storage/sftpgo/id_ecdsa ]]; then + ssh-keygen -t ecdsa -b 521 -f /var/azuracast/storage/sftpgo/id_ecdsa -q -N "" fi -if [[ ! -f /var/azuracast/sftpgo/persist/id_ed25519 ]]; then - ssh-keygen -t ed25519 -f /var/azuracast/sftpgo/persist/id_ed25519 -q -N "" +if [[ ! -f /var/azuracast/storage/sftpgo/id_ed25519 ]]; then + ssh-keygen -t ed25519 -f /var/azuracast/storage/sftpgo/id_ed25519 -q -N "" fi -chown -R azuracast:azuracast /var/azuracast/sftpgo/persist +chown -R azuracast:azuracast /var/azuracast/storage/sftpgo