Merge commit 'fa79a035eaa3510636839978c82ca56b5d4044fd'
This commit is contained in:
parent
693e4378f0
commit
cbad2a0293
18
Dockerfile
18
Dockerfile
|
@ -41,33 +41,32 @@ COPY ./util/docker/common /bd_build/
|
|||
RUN chmod a+x /bd_build/*.sh \
|
||||
&& /bd_build/prepare.sh \
|
||||
&& /bd_build/add_user.sh \
|
||||
&& /bd_build/cleanup.sh
|
||||
&& /bd_build/cleanup.sh \
|
||||
&& rm -rf /bd_build
|
||||
|
||||
# Build each set of dependencies in their own step for cacheability.
|
||||
ARG ARM_FULL_BUILD
|
||||
|
||||
COPY ./util/docker/supervisor /bd_build/supervisor/
|
||||
RUN bash /bd_build/supervisor/setup.sh \
|
||||
&& rm -rf /bd_build/supervisor
|
||||
|
||||
COPY ./util/docker/stations /bd_build/stations/
|
||||
RUN bash /bd_build/stations/setup.sh \
|
||||
&& bash /bd_build/cleanup.sh \
|
||||
&& rm -rf /bd_build/stations
|
||||
|
||||
COPY ./util/docker/web /bd_build/web/
|
||||
RUN bash /bd_build/web/setup.sh \
|
||||
&& bash /bd_build/cleanup.sh \
|
||||
&& rm -rf /bd_build/web
|
||||
|
||||
COPY ./util/docker/mariadb /bd_build/mariadb/
|
||||
RUN bash /bd_build/mariadb/setup.sh \
|
||||
&& bash /bd_build/cleanup.sh \
|
||||
&& rm -rf /bd_build/mariadb
|
||||
|
||||
COPY ./util/docker/redis /bd_build/redis/
|
||||
RUN bash /bd_build/redis/setup.sh \
|
||||
&& bash /bd_build/cleanup.sh \
|
||||
&& rm -rf /bd_build/redis
|
||||
|
||||
RUN bash /bd_build/post_setup.sh \
|
||||
&& rm -rf /bd_build
|
||||
|
||||
#
|
||||
# START Operations as `azuracast` user
|
||||
#
|
||||
|
@ -102,6 +101,7 @@ EXPOSE 8000-8999
|
|||
ENV LANG="en_US.UTF-8" \
|
||||
DOCKER_IS_STANDALONE="true" \
|
||||
APPLICATION_ENV="production" \
|
||||
MARIADB_AUTO_UPGRADE=1 \
|
||||
MYSQL_HOST="localhost" \
|
||||
MYSQL_PORT=3306 \
|
||||
MYSQL_USER="azuracast" \
|
||||
|
@ -122,5 +122,5 @@ ENV LANG="en_US.UTF-8" \
|
|||
PROFILING_EXTENSION_HTTP_IP_WHITELIST=*
|
||||
|
||||
# Entrypoint and default command
|
||||
ENTRYPOINT ["/usr/local/bin/my_init"]
|
||||
ENTRYPOINT ["tini", "--", "/usr/local/bin/my_init"]
|
||||
CMD ["--no-main-command"]
|
||||
|
|
|
@ -7,9 +7,6 @@ return function (App\Event\BuildConsoleCommands $event) {
|
|||
'azuracast:backup' => Command\Backup\BackupCommand::class,
|
||||
'azuracast:restore' => Command\Backup\RestoreCommand::class,
|
||||
'azuracast:debug:optimize-tables' => Command\Debug\OptimizeTablesCommand::class,
|
||||
'azuracast:internal:liquidsoap' => Command\Internal\LiquidsoapCommand::class,
|
||||
'azuracast:internal:sftp-event' => Command\Internal\SftpEventCommand::class,
|
||||
'azuracast:internal:sftp-auth' => Command\Internal\SftpAuthCommand::class,
|
||||
'azuracast:internal:on-ssl-renewal' => Command\Internal\OnSslRenewal::class,
|
||||
'azuracast:internal:ip' => Command\Internal\GetIpCommand::class,
|
||||
'azuracast:locale:generate' => Command\Locale\GenerateCommand::class,
|
||||
|
|
|
@ -61,6 +61,12 @@ return static function (RouteCollectorProxy $app) {
|
|||
}
|
||||
)->add(Middleware\GetStation::class);
|
||||
|
||||
$group->post('/sftp-auth', Controller\Api\Internal\SftpAuthAction::class)
|
||||
->setName('api:internal:sftp-auth');
|
||||
|
||||
$group->post('/sftp-event', Controller\Api\Internal\SftpEventAction::class)
|
||||
->setName('api:internal:sftp-event');
|
||||
|
||||
$group->get('/relays', Controller\Api\Admin\RelaysController::class)
|
||||
->setName('api:internal:relays')
|
||||
->add(Middleware\RequireLogin::class);
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Console\Command\Internal;
|
||||
|
||||
use App\Console\Command\CommandAbstract;
|
||||
use App\Entity;
|
||||
use App\Entity\Repository\StationRepository;
|
||||
use App\Radio\Backend\Liquidsoap\Command\AbstractCommand;
|
||||
use App\Radio\Enums\LiquidsoapCommands;
|
||||
use LogicException;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Throwable;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'azuracast:internal:liquidsoap',
|
||||
description: 'Handle Liquidsoap API calls.',
|
||||
)]
|
||||
class LiquidsoapCommand extends CommandAbstract
|
||||
{
|
||||
public function __construct(
|
||||
protected StationRepository $stationRepo,
|
||||
protected ContainerInterface $di,
|
||||
protected LoggerInterface $logger,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->addArgument('action', InputArgument::REQUIRED)
|
||||
->addArgument('station-id', InputArgument::REQUIRED)
|
||||
->addOption(
|
||||
'as-autodj',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'Whether the task is executing as the actual AutoDJ or as a test.'
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$stationId = $input->getArgument('station-id');
|
||||
$action = $input->getArgument('action');
|
||||
$asAutoDj = (bool)$input->getOption('as-autodj');
|
||||
|
||||
$payload = trim(getenv('PAYLOAD') ?: '');
|
||||
if (!empty($payload)) {
|
||||
$payload = json_decode($payload, true, 512, JSON_THROW_ON_ERROR);
|
||||
} else {
|
||||
$payload = [];
|
||||
}
|
||||
|
||||
try {
|
||||
$station = $this->stationRepo->findByIdentifier($stationId);
|
||||
if (!($station instanceof Entity\Station)) {
|
||||
throw new LogicException('Station not found.');
|
||||
}
|
||||
|
||||
$command = LiquidsoapCommands::tryFrom($action);
|
||||
if (null === $command || !$this->di->has($command->getClass())) {
|
||||
throw new LogicException('Command not found.');
|
||||
}
|
||||
|
||||
/** @var AbstractCommand $commandObj */
|
||||
$commandObj = $this->di->get($command->getClass());
|
||||
|
||||
$result = $commandObj->run($station, $asAutoDj, $payload);
|
||||
$io->writeln($result);
|
||||
} catch (Throwable $e) {
|
||||
$this->logger->error(
|
||||
sprintf(
|
||||
'Liquidsoap command "%s" error: %s',
|
||||
$action,
|
||||
$e->getMessage()
|
||||
),
|
||||
[
|
||||
'station' => $stationId,
|
||||
'payload' => $payload,
|
||||
'as-autodj' => $asAutoDj,
|
||||
]
|
||||
);
|
||||
|
||||
$io->writeln('false');
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -2,45 +2,40 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Console\Command\Internal;
|
||||
namespace App\Controller\Api\Internal;
|
||||
|
||||
use App\Console\Command\CommandAbstract;
|
||||
use App\Entity\SftpUser;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use Brick\Math\BigInteger;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
use const JSON_THROW_ON_ERROR;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'azuracast:internal:sftp-auth',
|
||||
description: 'Attempt SFTP authentication.',
|
||||
)]
|
||||
class SftpAuthCommand extends CommandAbstract
|
||||
final class SftpAuthAction
|
||||
{
|
||||
public function __construct(
|
||||
protected EntityManagerInterface $em,
|
||||
protected LoggerInterface $logger,
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$errorResponse = json_encode(['username' => ''], JSON_THROW_ON_ERROR);
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response
|
||||
): ResponseInterface {
|
||||
$errorResponse = $response
|
||||
->withStatus(500)
|
||||
->withJson(['username' => '']);
|
||||
|
||||
$username = getenv('SFTPGO_AUTHD_USERNAME') ?: '';
|
||||
$password = getenv('SFTPGO_AUTHD_PASSWORD') ?: '';
|
||||
$pubKey = getenv('SFTPGO_AUTHD_PUBLIC_KEY') ?: '';
|
||||
$parsedBody = $request->getParsedBody();
|
||||
|
||||
$username = $parsedBody['username'] ?? '';
|
||||
$password = $parsedBody['password'] ?? '';
|
||||
$pubKey = $parsedBody['public_key'] ?? '';
|
||||
|
||||
if (empty($username)) {
|
||||
$io->write($errorResponse);
|
||||
return 1;
|
||||
return $errorResponse;
|
||||
}
|
||||
|
||||
$sftpUser = $this->em->getRepository(SftpUser::class)->findOneBy(['username' => $username]);
|
||||
|
@ -52,8 +47,7 @@ class SftpAuthCommand extends CommandAbstract
|
|||
)
|
||||
);
|
||||
|
||||
$io->write($errorResponse);
|
||||
return 1;
|
||||
return $errorResponse;
|
||||
}
|
||||
|
||||
if (!$sftpUser->authenticate($password, $pubKey)) {
|
||||
|
@ -68,8 +62,7 @@ class SftpAuthCommand extends CommandAbstract
|
|||
]
|
||||
);
|
||||
|
||||
$io->write($errorResponse);
|
||||
return 1;
|
||||
return $errorResponse;
|
||||
}
|
||||
|
||||
$storageLocation = $sftpUser->getStation()->getMediaStorageLocation();
|
||||
|
@ -83,8 +76,7 @@ class SftpAuthCommand extends CommandAbstract
|
|||
)
|
||||
);
|
||||
|
||||
$io->write($errorResponse);
|
||||
return 1;
|
||||
return $errorResponse;
|
||||
}
|
||||
|
||||
$quotaRaw = $storageLocation->getStorageQuotaBytes();
|
||||
|
@ -105,7 +97,6 @@ class SftpAuthCommand extends CommandAbstract
|
|||
],
|
||||
];
|
||||
|
||||
$io->write(json_encode($row, JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK));
|
||||
return 0;
|
||||
return $response->withJson($row);
|
||||
}
|
||||
}
|
|
@ -2,90 +2,104 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Console\Command\Internal;
|
||||
namespace App\Controller\Api\Internal;
|
||||
|
||||
use App\Console\Command\CommandAbstract;
|
||||
use App\Entity;
|
||||
use App\Entity\SftpUser;
|
||||
use App\Entity\StorageLocation;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Media\BatchUtilities;
|
||||
use App\Message;
|
||||
use App\Message\AddNewMediaMessage;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use League\Flysystem\PathPrefixer;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Messenger\MessageBus;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'azuracast:internal:sftp-event',
|
||||
description: 'Send upcoming song feedback from the AutoDJ back to AzuraCast.',
|
||||
)]
|
||||
class SftpEventCommand extends CommandAbstract
|
||||
final class SftpEventAction
|
||||
{
|
||||
public function __construct(
|
||||
protected EntityManagerInterface $em,
|
||||
protected MessageBus $messageBus,
|
||||
protected LoggerInterface $logger,
|
||||
protected BatchUtilities $batchUtilities,
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly MessageBus $messageBus,
|
||||
private readonly LoggerInterface $logger,
|
||||
private readonly BatchUtilities $batchUtilities,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$action = getenv('SFTPGO_ACTION') ?: null;
|
||||
$username = getenv('SFTPGO_ACTION_USERNAME') ?: null;
|
||||
$path = getenv('SFTPGO_ACTION_PATH') ?: null;
|
||||
$targetPath = getenv('SFTPGO_ACTION_TARGET') ?: null;
|
||||
$sshCmd = getenv('SFTPGO_ACTION_SSH_CMD') ?: null;
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response
|
||||
): ResponseInterface {
|
||||
$errorResponse = $response->withStatus(500)->withJson(['success' => false]);
|
||||
|
||||
$parsedBody = $request->getParsedBody();
|
||||
|
||||
$action = $parsedBody['action'] ?? null;
|
||||
$username = $parsedBody['username'] ?? null;
|
||||
$path = $parsedBody['path'] ?? null;
|
||||
$targetPath = $parsedBody['target_path'] ?? null;
|
||||
$sshCmd = $parsedBody['ssh_cmd'] ?? null;
|
||||
|
||||
$this->logger->notice(
|
||||
'SFTP file event triggered',
|
||||
[
|
||||
'action' => $action,
|
||||
'username' => $username,
|
||||
'path' => $path,
|
||||
'action' => $action,
|
||||
'username' => $username,
|
||||
'path' => $path,
|
||||
'targetPath' => $targetPath,
|
||||
'sshCmd' => $sshCmd,
|
||||
'sshCmd' => $sshCmd,
|
||||
]
|
||||
);
|
||||
|
||||
// Determine which station the username belongs to.
|
||||
$sftpUser = $this->em->getRepository(Entity\SftpUser::class)->findOneBy(
|
||||
$sftpUser = $this->em->getRepository(SftpUser::class)->findOneBy(
|
||||
[
|
||||
'username' => $username,
|
||||
]
|
||||
);
|
||||
|
||||
if (!$sftpUser instanceof Entity\SftpUser) {
|
||||
if (!$sftpUser instanceof SftpUser) {
|
||||
$this->logger->error('SFTP Username not found.', ['username' => $username]);
|
||||
return 1;
|
||||
return $errorResponse;
|
||||
}
|
||||
|
||||
$storageLocation = $sftpUser->getStation()->getMediaStorageLocation();
|
||||
|
||||
if (!$storageLocation->isLocal()) {
|
||||
$this->logger->error(sprintf('Storage location "%s" is not local.', $storageLocation));
|
||||
return 1;
|
||||
return $errorResponse;
|
||||
}
|
||||
|
||||
if (null === $path) {
|
||||
$this->logger->error('No path specified for action.');
|
||||
return 1;
|
||||
return $errorResponse;
|
||||
}
|
||||
|
||||
return match ($action) {
|
||||
'upload' => $this->handleNewUpload($storageLocation, $path),
|
||||
'pre-delete' => $this->handleDelete($storageLocation, $path),
|
||||
'rename' => $this->handleRename($storageLocation, $path, $targetPath),
|
||||
default => 1,
|
||||
};
|
||||
try {
|
||||
match ($action) {
|
||||
'upload' => $this->handleNewUpload($storageLocation, $path),
|
||||
'pre-delete' => $this->handleDelete($storageLocation, $path),
|
||||
'rename' => $this->handleRename($storageLocation, $path, $targetPath),
|
||||
default => null,
|
||||
};
|
||||
|
||||
return $response->withJson(['success' => true]);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error(
|
||||
sprintf('SFTP Event: %s', $e->getMessage()),
|
||||
[
|
||||
'exception' => $e,
|
||||
]
|
||||
);
|
||||
|
||||
return $errorResponse;
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleNewUpload(
|
||||
Entity\StorageLocation $storageLocation,
|
||||
private function handleNewUpload(
|
||||
StorageLocation $storageLocation,
|
||||
string $path
|
||||
): int {
|
||||
): void {
|
||||
$pathPrefixer = new PathPrefixer($storageLocation->getPath(), DIRECTORY_SEPARATOR);
|
||||
$relativePath = $pathPrefixer->stripPrefix($path);
|
||||
|
||||
|
@ -93,23 +107,21 @@ class SftpEventCommand extends CommandAbstract
|
|||
'Processing new SFTP upload.',
|
||||
[
|
||||
'storageLocation' => (string)$storageLocation,
|
||||
'path' => $relativePath,
|
||||
'path' => $relativePath,
|
||||
]
|
||||
);
|
||||
|
||||
$message = new Message\AddNewMediaMessage();
|
||||
$message = new AddNewMediaMessage();
|
||||
$message->storage_location_id = $storageLocation->getIdRequired();
|
||||
$message->path = $relativePath;
|
||||
|
||||
$this->messageBus->dispatch($message);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function handleDelete(
|
||||
Entity\StorageLocation $storageLocation,
|
||||
private function handleDelete(
|
||||
StorageLocation $storageLocation,
|
||||
string $path
|
||||
): int {
|
||||
): void {
|
||||
$pathPrefixer = new PathPrefixer($storageLocation->getPath(), DIRECTORY_SEPARATOR);
|
||||
$relativePath = $pathPrefixer->stripPrefix($path);
|
||||
|
||||
|
@ -117,7 +129,7 @@ class SftpEventCommand extends CommandAbstract
|
|||
'Processing SFTP file/folder deletion.',
|
||||
[
|
||||
'storageLocation' => (string)$storageLocation,
|
||||
'path' => $relativePath,
|
||||
'path' => $relativePath,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -140,18 +152,15 @@ class SftpEventCommand extends CommandAbstract
|
|||
);
|
||||
|
||||
$fs->delete($relativePath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function handleRename(
|
||||
Entity\StorageLocation $storageLocation,
|
||||
private function handleRename(
|
||||
StorageLocation $storageLocation,
|
||||
string $path,
|
||||
?string $newPath
|
||||
): int {
|
||||
): void {
|
||||
if (null === $newPath) {
|
||||
$this->logger->error('No new path specified for rename.');
|
||||
return 1;
|
||||
throw new \LogicException('No new path specified for rename.');
|
||||
}
|
||||
|
||||
$pathPrefixer = new PathPrefixer($storageLocation->getPath(), DIRECTORY_SEPARATOR);
|
||||
|
@ -163,8 +172,8 @@ class SftpEventCommand extends CommandAbstract
|
|||
'Processing SFTP file/folder rename.',
|
||||
[
|
||||
'storageLocation' => (string)$storageLocation,
|
||||
'from' => $from,
|
||||
'to' => $to,
|
||||
'from' => $from,
|
||||
'to' => $to,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -173,7 +182,5 @@ class SftpEventCommand extends CommandAbstract
|
|||
$to,
|
||||
$storageLocation
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -1,16 +1,14 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install sudo
|
||||
apt-get install -y --no-install-recommends sudo
|
||||
|
||||
# Workaround for sudo errors in containers, see: https://github.com/sudo-project/sudo/issues/42
|
||||
echo "Set disable_coredump false" >> /etc/sudo.conf
|
||||
|
||||
adduser --home /var/azuracast --disabled-password --gecos "" azuracast
|
||||
|
||||
usermod -aG docker_env azuracast
|
||||
usermod -aG www-data azuracast
|
||||
|
||||
mkdir -p /var/azuracast/www /var/azuracast/stations /var/azuracast/servers/shoutcast2 \
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
export LC_ALL=C
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
minimal_apt_get_install='apt-get install -y --no-install-recommends'
|
||||
|
||||
install_without_postinst() {
|
||||
local PACKAGE
|
||||
PACKAGE=$1
|
||||
|
||||
mkdir -p /tmp/install_$PACKAGE
|
||||
cd /tmp/install_$PACKAGE
|
||||
|
||||
apt-get download $PACKAGE
|
||||
dpkg --unpack $PACKAGE*.deb
|
||||
rm -f /var/lib/dpkg/info/$PACKAGE.postinst
|
||||
dpkg --configure $PACKAGE
|
||||
|
||||
apt-get install -yf #To fix dependencies
|
||||
|
||||
cd /
|
||||
rm -rf /tmp/install_$PACKAGE
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
apt-get -y autoremove
|
||||
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
rm -rf /tmp/tmp*
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
chmod -R a+x /usr/local/bin
|
||||
chmod -R +x /etc/my_init.d
|
||||
chmod -R +x /etc/my_init.pre_shutdown.d
|
||||
chmod -R +x /etc/my_init.post_shutdown.d
|
||||
|
||||
ln -s /etc/service.minimal/* /etc/service
|
||||
ln -s /etc/service.full/* /etc/service
|
||||
|
||||
chmod -R +x /etc/service.minimal
|
||||
chmod -R +x /etc/service.full
|
||||
chmod -R +x /etc/service
|
|
@ -1,14 +1,11 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
## Prevent initramfs updates from trying to run grub and lilo.
|
||||
## https://journal.paul.querna.org/articles/2013/10/15/docker-ubuntu-on-rackspace/
|
||||
## http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=594189
|
||||
export INITRD=no
|
||||
mkdir -p /etc/container_environment
|
||||
echo -n no > /etc/container_environment/INITRD
|
||||
|
||||
# Add default timezone.
|
||||
echo "UTC" > /etc/timezone
|
||||
|
@ -35,46 +32,29 @@ dpkg-divert --local --rename --add /usr/bin/ischroot
|
|||
ln -sf /bin/true /usr/bin/ischroot
|
||||
|
||||
# apt-utils fix for Ubuntu 16.04
|
||||
$minimal_apt_get_install apt-utils
|
||||
apt-get install -y --no-install-recommends apt-utils
|
||||
|
||||
## Install HTTPS support for APT.
|
||||
$minimal_apt_get_install apt-transport-https ca-certificates
|
||||
apt-get install -y --no-install-recommends apt-transport-https ca-certificates
|
||||
|
||||
## Install add-apt-repository
|
||||
$minimal_apt_get_install software-properties-common
|
||||
apt-get install -y --no-install-recommends software-properties-common
|
||||
|
||||
## Upgrade all packages.
|
||||
apt-get dist-upgrade -y --no-install-recommends -o Dpkg::Options::="--force-confold"
|
||||
|
||||
## Fix locale.
|
||||
$minimal_apt_get_install language-pack-en
|
||||
apt-get install -y --no-install-recommends language-pack-en
|
||||
|
||||
locale-gen en_US
|
||||
update-locale LANG=en_US.UTF-8 LC_CTYPE=en_US.UTF-8
|
||||
|
||||
echo -n en_US.UTF-8 > /etc/container_environment/LANG
|
||||
echo -n en_US.UTF-8 > /etc/container_environment/LC_CTYPE
|
||||
|
||||
# Make init folders
|
||||
mkdir -p /etc/my_init.d
|
||||
mkdir -p /etc/my_init.pre_shutdown.d
|
||||
mkdir -p /etc/my_init.post_shutdown.d
|
||||
mkdir -p /etc/container_environment
|
||||
touch /etc/container_environment.sh
|
||||
touch /etc/container_environment.json
|
||||
chmod 700 /etc/container_environment
|
||||
|
||||
groupadd -g 8377 docker_env
|
||||
chown :docker_env /etc/container_environment.sh /etc/container_environment.json
|
||||
chmod 640 /etc/container_environment.sh /etc/container_environment.json
|
||||
ln -s /etc/container_environment.sh /etc/profile.d/
|
||||
|
||||
# Install runit and other common scripts.
|
||||
$minimal_apt_get_install runit gosu curl wget tar zip unzip git rsync tzdata gpg-agent openssh-client
|
||||
# Install other common scripts.
|
||||
apt-get install -y --no-install-recommends tini gosu curl wget tar zip unzip git rsync tzdata gpg-agent openssh-client
|
||||
|
||||
# Add scripts
|
||||
cp -rT /bd_build/scripts/ /usr/local/bin
|
||||
chmod -R a+x /usr/local/bin
|
||||
|
||||
mkdir -p /etc/service.full/
|
||||
mkdir -p /etc/service.minimal/
|
||||
|
|
|
@ -1,402 +1,29 @@
|
|||
#!/usr/bin/python3 -u
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/bin/bash
|
||||
|
||||
import argparse
|
||||
import errno
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import signal
|
||||
import stat
|
||||
import sys
|
||||
import time
|
||||
# Write environment variables to script
|
||||
declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env
|
||||
chmod 744 /container.env
|
||||
|
||||
ENV_INIT_DIRECTORY = os.environ.get('ENV_INIT_DIRECTORY', '/etc/my_init.d')
|
||||
# Run startup scripts
|
||||
for f in /etc/my_init.d/*.sh; do
|
||||
echo "** Running startup script '$f'..."
|
||||
bash "$f" -H
|
||||
echo "** Startup script complete."
|
||||
done
|
||||
|
||||
KILL_PROCESS_TIMEOUT = int(os.environ.get('KILL_PROCESS_TIMEOUT', 30))
|
||||
KILL_ALL_PROCESSES_TIMEOUT = int(os.environ.get('KILL_ALL_PROCESSES_TIMEOUT', 30))
|
||||
echo "** Running Supervisord..."
|
||||
|
||||
LOG_LEVEL_ERROR = 1
|
||||
LOG_LEVEL_WARN = 1
|
||||
LOG_LEVEL_INFO = 2
|
||||
LOG_LEVEL_DEBUG = 3
|
||||
if [ "$1" = '--no-main-command' ]; then
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord-full.conf --nodaemon
|
||||
fi
|
||||
|
||||
SHENV_NAME_WHITELIST_REGEX = re.compile('\W')
|
||||
/usr/bin/supervisord -c /etc/supervisor/supervisord-minimal.conf
|
||||
|
||||
log_level = None
|
||||
echo "** Supervisord started."
|
||||
echo "** Running uptime_wait..."
|
||||
|
||||
terminated_child_processes = {}
|
||||
uptime_wait
|
||||
|
||||
_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
|
||||
echo "** Services up and ready!"
|
||||
|
||||
class AlarmException(Exception):
|
||||
pass
|
||||
|
||||
def error(message):
|
||||
if log_level >= LOG_LEVEL_ERROR:
|
||||
sys.stderr.write("*** %s\n" % message)
|
||||
|
||||
def warn(message):
|
||||
if log_level >= LOG_LEVEL_WARN:
|
||||
sys.stderr.write("*** %s\n" % message)
|
||||
|
||||
def info(message):
|
||||
if log_level >= LOG_LEVEL_INFO:
|
||||
sys.stderr.write("*** %s\n" % message)
|
||||
|
||||
def debug(message):
|
||||
if log_level >= LOG_LEVEL_DEBUG:
|
||||
sys.stderr.write("*** %s\n" % message)
|
||||
|
||||
def ignore_signals_and_raise_keyboard_interrupt(signame):
|
||||
signal.signal(signal.SIGTERM, signal.SIG_IGN)
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
raise KeyboardInterrupt(signame)
|
||||
|
||||
def raise_alarm_exception():
|
||||
raise AlarmException('Alarm')
|
||||
|
||||
def listdir(path):
|
||||
try:
|
||||
result = os.stat(path)
|
||||
except OSError:
|
||||
return []
|
||||
if stat.S_ISDIR(result.st_mode):
|
||||
return sorted(os.listdir(path))
|
||||
else:
|
||||
return []
|
||||
|
||||
def is_exe(path):
|
||||
try:
|
||||
return os.path.isfile(path) and os.access(path, os.X_OK)
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
def import_envvars(clear_existing_environment=True, override_existing_environment=True):
|
||||
if not os.path.exists("/etc/container_environment"):
|
||||
return
|
||||
new_env = {}
|
||||
for envfile in listdir("/etc/container_environment"):
|
||||
name = os.path.basename(envfile)
|
||||
with open("/etc/container_environment/" + envfile, "r") as f:
|
||||
# Text files often end with a trailing newline, which we
|
||||
# don't want to include in the env variable value. See
|
||||
# https://github.com/phusion/baseimage-docker/pull/49
|
||||
value = re.sub('\n\Z', '', f.read())
|
||||
new_env[name] = value
|
||||
if clear_existing_environment:
|
||||
os.environ.clear()
|
||||
for name, value in new_env.items():
|
||||
if override_existing_environment or name not in os.environ:
|
||||
os.environ[name] = value
|
||||
|
||||
def export_envvars(to_dir=True):
|
||||
if not os.path.exists("/etc/container_environment"):
|
||||
return
|
||||
shell_dump = ""
|
||||
for name, value in os.environ.items():
|
||||
if name in ['HOME', 'USER', 'GROUP', 'UID', 'GID', 'SHELL']:
|
||||
continue
|
||||
if to_dir:
|
||||
with open("/etc/container_environment/" + name, "w") as f:
|
||||
f.write(value)
|
||||
shell_dump += "export " + sanitize_shenvname(name) + "=" + shquote(value) + "\n"
|
||||
with open("/etc/container_environment.sh", "w") as f:
|
||||
f.write(shell_dump)
|
||||
with open("/etc/container_environment.json", "w") as f:
|
||||
f.write(json.dumps(dict(os.environ)))
|
||||
|
||||
def shquote(s):
|
||||
"""Return a shell-escaped version of the string *s*."""
|
||||
if not s:
|
||||
return "''"
|
||||
if _find_unsafe(s) is None:
|
||||
return s
|
||||
|
||||
# use single quotes, and put single quotes into double quotes
|
||||
# the string $'b is then quoted as '$'"'"'b'
|
||||
return "'" + s.replace("'", "'\"'\"'") + "'"
|
||||
|
||||
def sanitize_shenvname(s):
|
||||
"""Return string with [0-9a-zA-Z_] characters"""
|
||||
return re.sub(SHENV_NAME_WHITELIST_REGEX, "_", s)
|
||||
|
||||
# Waits for the child process with the given PID, while at the same time
|
||||
# reaping any other child processes that have exited (e.g. adopted child
|
||||
# processes that have terminated).
|
||||
def waitpid_reap_other_children(pid):
|
||||
global terminated_child_processes
|
||||
|
||||
status = terminated_child_processes.get(pid)
|
||||
if status:
|
||||
# A previous call to waitpid_reap_other_children(),
|
||||
# with an argument not equal to the current argument,
|
||||
# already waited for this process. Return the status
|
||||
# that was obtained back then.
|
||||
del terminated_child_processes[pid]
|
||||
return status
|
||||
|
||||
done = False
|
||||
status = None
|
||||
while not done:
|
||||
try:
|
||||
# https://github.com/phusion/baseimage-docker/issues/151#issuecomment-92660569
|
||||
this_pid, status = os.waitpid(pid, os.WNOHANG)
|
||||
if this_pid == 0:
|
||||
this_pid, status = os.waitpid(-1, 0)
|
||||
if this_pid == pid:
|
||||
done = True
|
||||
else:
|
||||
# Save status for later.
|
||||
terminated_child_processes[this_pid] = status
|
||||
except OSError as e:
|
||||
if e.errno == errno.ECHILD or e.errno == errno.ESRCH:
|
||||
return None
|
||||
else:
|
||||
raise
|
||||
return status
|
||||
|
||||
def stop_child_process(name, pid, signo=signal.SIGTERM, time_limit=KILL_PROCESS_TIMEOUT):
|
||||
info("Shutting down %s (PID %d)..." % (name, pid))
|
||||
try:
|
||||
os.kill(pid, signo)
|
||||
except OSError:
|
||||
pass
|
||||
signal.alarm(time_limit)
|
||||
try:
|
||||
try:
|
||||
waitpid_reap_other_children(pid)
|
||||
except OSError:
|
||||
pass
|
||||
except AlarmException:
|
||||
warn("%s (PID %d) did not shut down in time. Forcing it to exit." % (name, pid))
|
||||
try:
|
||||
os.kill(pid, signal.SIGKILL)
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
waitpid_reap_other_children(pid)
|
||||
except OSError:
|
||||
pass
|
||||
finally:
|
||||
signal.alarm(0)
|
||||
|
||||
def run_command_killable(*argv):
|
||||
filename = argv[0]
|
||||
status = None
|
||||
pid = os.spawnvp(os.P_NOWAIT, filename, argv)
|
||||
try:
|
||||
status = waitpid_reap_other_children(pid)
|
||||
except BaseException:
|
||||
warn("An error occurred. Aborting.")
|
||||
stop_child_process(filename, pid)
|
||||
raise
|
||||
if status != 0:
|
||||
if status is None:
|
||||
error("%s exited with unknown status\n" % filename)
|
||||
else:
|
||||
error("%s failed with status %d\n" % (filename, os.WEXITSTATUS(status)))
|
||||
sys.exit(1)
|
||||
|
||||
def run_command_killable_and_import_envvars(*argv):
|
||||
run_command_killable(*argv)
|
||||
import_envvars()
|
||||
export_envvars(False)
|
||||
|
||||
def kill_all_processes(time_limit):
|
||||
info("Killing all processes...")
|
||||
try:
|
||||
os.kill(-1, signal.SIGTERM)
|
||||
except OSError:
|
||||
pass
|
||||
signal.alarm(time_limit)
|
||||
try:
|
||||
# Wait until no more child processes exist.
|
||||
done = False
|
||||
while not done:
|
||||
try:
|
||||
os.waitpid(-1, 0)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ECHILD:
|
||||
done = True
|
||||
else:
|
||||
raise
|
||||
except AlarmException:
|
||||
warn("Not all processes have exited in time. Forcing them to exit.")
|
||||
try:
|
||||
os.kill(-1, signal.SIGKILL)
|
||||
except OSError:
|
||||
pass
|
||||
finally:
|
||||
signal.alarm(0)
|
||||
|
||||
|
||||
def run_startup_files():
|
||||
# Run ENV_INIT_DIRECTORY/*
|
||||
for name in listdir(ENV_INIT_DIRECTORY):
|
||||
filename = os.path.join(ENV_INIT_DIRECTORY, name)
|
||||
if is_exe(filename):
|
||||
info("Running %s..." % filename)
|
||||
run_command_killable_and_import_envvars(filename)
|
||||
|
||||
# Run /etc/rc.local.
|
||||
if is_exe("/etc/rc.local"):
|
||||
info("Running /etc/rc.local...")
|
||||
run_command_killable_and_import_envvars("/etc/rc.local")
|
||||
|
||||
def run_pre_shutdown_scripts():
|
||||
debug("Running pre-shutdown scripts...")
|
||||
|
||||
# Run /etc/my_init.pre_shutdown.d/*
|
||||
for name in listdir("/etc/my_init.pre_shutdown.d"):
|
||||
filename = "/etc/my_init.pre_shutdown.d/" + name
|
||||
if is_exe(filename):
|
||||
info("Running %s..." % filename)
|
||||
run_command_killable(filename)
|
||||
|
||||
def run_post_shutdown_scripts():
|
||||
debug("Running post-shutdown scripts...")
|
||||
|
||||
# Run /etc/my_init.post_shutdown.d/*
|
||||
for name in listdir("/etc/my_init.post_shutdown.d"):
|
||||
filename = "/etc/my_init.post_shutdown.d/" + name
|
||||
if is_exe(filename):
|
||||
info("Running %s..." % filename)
|
||||
run_command_killable(filename)
|
||||
|
||||
def start_runit(runit_services_dir):
|
||||
info("Booting runit daemon...")
|
||||
pid = os.spawnl(os.P_NOWAIT, "/usr/bin/runsvdir", "/usr/bin/runsvdir", "-P", runit_services_dir)
|
||||
info("Runit started as PID %d" % pid)
|
||||
return pid
|
||||
|
||||
def wait_for_runit_or_interrupt(pid):
|
||||
status = waitpid_reap_other_children(pid)
|
||||
return (True, status)
|
||||
|
||||
def shutdown_runit_services(runit_services_dir, quiet=False):
|
||||
if not quiet:
|
||||
debug("Begin shutting down runit services...")
|
||||
os.system("/usr/bin/sv -w %d force-stop %s/* > /dev/null" % (KILL_PROCESS_TIMEOUT, runit_services_dir))
|
||||
|
||||
def wait_for_runit_services(runit_services_dir):
|
||||
debug("Waiting for runit services to exit...")
|
||||
done = False
|
||||
while not done:
|
||||
done = os.system("/usr/bin/sv status %s/* | grep -q '^run:'" % runit_services_dir) != 0
|
||||
if not done:
|
||||
time.sleep(0.1)
|
||||
# According to https://github.com/phusion/baseimage-docker/issues/315
|
||||
# there is a bug or race condition in Runit, causing it
|
||||
# not to shutdown services that are already being started.
|
||||
# So during shutdown we repeatedly instruct Runit to shutdown
|
||||
# services.
|
||||
shutdown_runit_services(runit_services_dir, True)
|
||||
|
||||
def main(args):
|
||||
import_envvars(False, False)
|
||||
export_envvars()
|
||||
|
||||
if not args.skip_startup_files:
|
||||
run_startup_files()
|
||||
|
||||
runit_exited = False
|
||||
exit_code = None
|
||||
|
||||
if not args.skip_runit:
|
||||
runit_services_dir = '/etc/service.minimal'
|
||||
if len(args.main_command) == 0 or args.no_main_command:
|
||||
runit_services_dir = '/etc/service'
|
||||
|
||||
runit_pid = start_runit(runit_services_dir)
|
||||
|
||||
try:
|
||||
exit_status = None
|
||||
if len(args.main_command) == 0 or args.no_main_command:
|
||||
runit_exited, exit_code = wait_for_runit_or_interrupt(runit_pid)
|
||||
if runit_exited:
|
||||
if exit_code is None:
|
||||
info("Runit exited with unknown status")
|
||||
exit_status = 1
|
||||
else:
|
||||
exit_status = os.WEXITSTATUS(exit_code)
|
||||
info("Runit exited with status %d" % exit_status)
|
||||
else:
|
||||
main_command = ["uptime_wait"] + args.main_command
|
||||
|
||||
info("Running %s..." % " ".join(main_command))
|
||||
pid = os.spawnvp(os.P_NOWAIT, main_command[0], main_command)
|
||||
try:
|
||||
exit_code = waitpid_reap_other_children(pid)
|
||||
if exit_code is None:
|
||||
info("%s exited with unknown status." % main_command[0])
|
||||
exit_status = 1
|
||||
else:
|
||||
exit_status = os.WEXITSTATUS(exit_code)
|
||||
info("%s exited with status %d." % (main_command[0], exit_status))
|
||||
except KeyboardInterrupt:
|
||||
stop_child_process(main_command[0], pid)
|
||||
raise
|
||||
except BaseException:
|
||||
warn("An error occurred. Aborting.")
|
||||
stop_child_process(main_command[0], pid)
|
||||
raise
|
||||
sys.exit(exit_status)
|
||||
finally:
|
||||
if not args.skip_runit:
|
||||
run_pre_shutdown_scripts()
|
||||
shutdown_runit_services(runit_services_dir)
|
||||
|
||||
if not runit_exited:
|
||||
stop_child_process("runit daemon", runit_pid)
|
||||
|
||||
wait_for_runit_services(runit_services_dir)
|
||||
run_post_shutdown_scripts()
|
||||
|
||||
# Parse options.
|
||||
parser = argparse.ArgumentParser(description='Initialize the system.')
|
||||
|
||||
parser.add_argument('main_command', metavar='MAIN_COMMAND', type=str, nargs='*',
|
||||
help='The main command to run. (default: runit)')
|
||||
|
||||
parser.add_argument('--no-main-command', dest='no_main_command',
|
||||
action='store_const', const=True, default=False,
|
||||
help='Flag to provide as main command in the absence of one.')
|
||||
|
||||
parser.add_argument('--skip-startup-files', dest='skip_startup_files',
|
||||
action='store_const', const=True, default=False,
|
||||
help='Skip running /etc/my_init.d/* and /etc/rc.local')
|
||||
|
||||
parser.add_argument('--skip-runit', dest='skip_runit',
|
||||
action='store_const', const=True, default=False,
|
||||
help='Do not run runit services')
|
||||
|
||||
parser.add_argument('--no-kill-all-on-exit', dest='kill_all_on_exit',
|
||||
action='store_const', const=False, default=True,
|
||||
help='Don\'t kill all processes on the system upon exiting')
|
||||
|
||||
parser.add_argument('--quiet', dest='log_level',
|
||||
action='store_const', const=LOG_LEVEL_WARN, default=LOG_LEVEL_INFO,
|
||||
help='Only print warnings and errors')
|
||||
|
||||
args = parser.parse_args()
|
||||
log_level = args.log_level
|
||||
|
||||
if args.skip_runit and len(args.main_command) == 0:
|
||||
error("When --skip-runit is given, you must also pass a main command.")
|
||||
sys.exit(1)
|
||||
|
||||
# Run main function.
|
||||
signal.signal(signal.SIGTERM, lambda signum, frame: ignore_signals_and_raise_keyboard_interrupt('SIGTERM'))
|
||||
signal.signal(signal.SIGINT, lambda signum, frame: ignore_signals_and_raise_keyboard_interrupt('SIGINT'))
|
||||
signal.signal(signal.SIGALRM, lambda signum, frame: raise_alarm_exception())
|
||||
|
||||
try:
|
||||
main(args)
|
||||
except KeyboardInterrupt:
|
||||
warn("Init system aborted.")
|
||||
exit(2)
|
||||
finally:
|
||||
if args.kill_all_on_exit:
|
||||
kill_all_processes(KILL_ALL_PROCESSES_TIMEOUT)
|
||||
exec "$@"
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
[program:mariadb]
|
||||
command=mysqld
|
||||
user=mysql
|
||||
priority=100
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=unexpected
|
||||
|
||||
stdout_logfile=/proc/1/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/proc/1/fd/2
|
||||
stderr_logfile_maxbytes=0
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec mysqladmin ping -h localhost
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
dockerize -template /etc/mysql/db.cnf.tmpl:/etc/mysql/conf.d/db.cnf
|
||||
|
||||
exec gosu mysql mysqld
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
apt-get update
|
||||
|
@ -10,11 +9,20 @@ cp -rT /bd_build/mariadb/scripts/ /usr/local/bin
|
|||
|
||||
cp -rT /bd_build/mariadb/startup_scripts/. /etc/my_init.d/
|
||||
|
||||
cp -rT /bd_build/mariadb/service.minimal/. /etc/service.minimal/
|
||||
cp -rT /bd_build/mariadb/service.minimal/. /etc/supervisor/minimal.conf.d/
|
||||
|
||||
# cp -rT /bd_build/mariadb/service.full/. /etc/service.full/
|
||||
# cp -rT /bd_build/mariadb/service.full/. /etc/supervisor/full.conf.d/
|
||||
|
||||
# Run service setup for all setup scripts
|
||||
for f in /bd_build/mariadb/setup/*.sh; do
|
||||
bash "$f" -H
|
||||
done
|
||||
|
||||
# Cleanup
|
||||
apt-get -y autoremove
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
rm -rf /tmp/tmp*
|
||||
|
||||
chmod -R a+x /usr/local/bin
|
||||
chmod -R +x /etc/my_init.d
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install tzdata libjemalloc2 pwgen xz-utils zstd dirmngr apt-transport-https
|
||||
apt-get install -y --no-install-recommends tzdata libjemalloc2 pwgen xz-utils zstd dirmngr apt-transport-https
|
||||
|
||||
sudo apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
|
||||
sudo add-apt-repository 'deb [arch=amd64,arm64,ppc64el,s390x] https://atl.mirrors.knownhost.com/mariadb/repo/10.7/ubuntu focal main'
|
||||
|
@ -17,7 +16,7 @@ export MARIADB_MAJOR=10.7
|
|||
} | debconf-set-selections;
|
||||
|
||||
apt update
|
||||
$minimal_apt_get_install mariadb-server mariadb-backup socat
|
||||
apt-get install -y --no-install-recommends mariadb-server mariadb-backup socat
|
||||
|
||||
# Temporary work around for MDEV-27980, closes #417
|
||||
sed --follow-symlinks -i -e 's/--loose-disable-plugin-file-key-management//' /usr/bin/mysql_install_db
|
||||
|
@ -43,9 +42,6 @@ else
|
|||
sed -i -e '/includedir/ {N;s/\(.*\)\n\(.*\)/[mariadbd]\nskip-host-cache\nskip-name-resolve\n\n\2\n\1/}' /etc/mysql/mariadb.cnf;
|
||||
fi
|
||||
|
||||
# Customizations to MariaDB
|
||||
echo "1" >> /etc/container_environment/MARIADB_AUTO_UPGRADE
|
||||
|
||||
mkdir /docker-entrypoint-initdb.d
|
||||
|
||||
cp /bd_build/mariadb/mariadb/db.sql /docker-entrypoint-initdb.d/00-azuracast.sql
|
||||
|
|
|
@ -4,6 +4,5 @@
|
|||
if [ "$MYSQL_HOST" != "localhost" ]; then
|
||||
echo "MariaDB host is not localhost; disabling MariaDB..."
|
||||
|
||||
rm -rf /etc/service/mariadb
|
||||
rm -rf /etc/service.minimal/mariadb
|
||||
rm -rf /etc/supervisor/minimal.conf.d/mariadb.conf
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ ! -f /etc/supervisor/minimal.conf.d/mariadb.conf ]; then
|
||||
echo "MariaDB disabled. Skipping DB initialization..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
dockerize -template /etc/mysql/db.cnf.tmpl:/etc/mysql/conf.d/db.cnf
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ ! -f /etc/service/mariadb/run ]; then
|
||||
if [ ! -f /etc/supervisor/minimal.conf.d/mariadb.conf ]; then
|
||||
echo "MariaDB disabled. Skipping DB initialization..."
|
||||
exit 0
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
[program:redis]
|
||||
command=redis-server /etc/redis/redis.conf
|
||||
user=redis
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=unexpected
|
||||
|
||||
stdout_logfile=/proc/1/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/proc/1/fd/2
|
||||
stderr_logfile_maxbytes=0
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec gosu redis redis-server /etc/redis/redis.conf
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
apt-get update
|
||||
|
@ -10,11 +9,20 @@ apt-get update
|
|||
|
||||
cp -rT /bd_build/redis/startup_scripts/. /etc/my_init.d/
|
||||
|
||||
cp -rT /bd_build/redis/service.minimal/. /etc/service.minimal/
|
||||
cp -rT /bd_build/redis/service.minimal/. /etc/supervisor/minimal.conf.d/
|
||||
|
||||
# cp -rT /bd_build/redis/service.full/. /etc/service.full/
|
||||
# cp -rT /bd_build/redis/service.full/. /etc/supervisor/full.conf.d/
|
||||
|
||||
# Run service setup for all setup scripts
|
||||
for f in /bd_build/redis/setup/*.sh; do
|
||||
bash "$f" -H
|
||||
done
|
||||
|
||||
# Cleanup
|
||||
apt-get -y autoremove
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
rm -rf /tmp/tmp*
|
||||
|
||||
chmod -R a+x /usr/local/bin
|
||||
chmod -R +x /etc/my_init.d
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
add-apt-repository -y ppa:chris-lea/redis-server
|
||||
apt-get update
|
||||
|
||||
$minimal_apt_get_install redis-server
|
||||
apt-get install -y --no-install-recommends redis-server
|
||||
|
||||
cp /bd_build/redis/redis/redis.conf /etc/redis/redis.conf
|
||||
chown redis:redis /etc/redis/redis.conf
|
||||
|
|
|
@ -12,6 +12,5 @@ ENABLE_REDIS=${ENABLE_REDIS:-true}
|
|||
|
||||
if [ "$REDIS_HOST" != "localhost" ] || ! bool "$ENABLE_REDIS"; then
|
||||
echo "Redis is disabled or host is not localhost; disabling Redis..."
|
||||
rm -rf /etc/service/redis
|
||||
rm -rf /etc/service.minimal/redis
|
||||
rm -rf /etc/supervisor/minimal.conf.d/redis.conf
|
||||
fi
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
sv -w 45 check php-fpm || exit 1
|
||||
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
apt-get update
|
||||
|
@ -10,11 +9,20 @@ apt-get update
|
|||
|
||||
# cp -rT /bd_build/stations/startup_scripts/. /etc/my_init.d/
|
||||
|
||||
# cp -rT /bd_build/stations/service.minimal/. /etc/service.minimal/
|
||||
# cp -rT /bd_build/stations/service.minimal/. /etc/supervisor/minimal.conf.d/
|
||||
|
||||
cp -rT /bd_build/stations/service.full/. /etc/service.full/
|
||||
# cp -rT /bd_build/stations/service.full/. /etc/supervisor/full.conf.d/
|
||||
|
||||
# Run service setup for all setup scripts
|
||||
for f in /bd_build/stations/setup/*.sh; do
|
||||
bash "$f" -H
|
||||
done
|
||||
|
||||
# Cleanup
|
||||
apt-get -y autoremove
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
rm -rf /tmp/tmp*
|
||||
|
||||
chmod -R a+x /usr/local/bin
|
||||
chmod -R +x /etc/my_init.d
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install flac
|
||||
apt-get install -y --no-install-recommends flac
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
# Only install Icecast deps (Icecast is handled by another container).
|
||||
$minimal_apt_get_install libxml2 libxslt1-dev libvorbis-dev
|
||||
apt-get install -y --no-install-recommends libxml2 libxslt1-dev libvorbis-dev
|
||||
|
||||
# SSL self-signed cert generation
|
||||
$minimal_apt_get_install openssl
|
||||
apt-get install -y --no-install-recommends openssl
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
# Packages required by Liquidsoap
|
||||
$minimal_apt_get_install libao-dev libasound2-dev libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev \
|
||||
apt-get install -y --no-install-recommends libao-dev libasound2-dev libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev \
|
||||
libavutil-dev libfaad-dev libfdk-aac-dev libflac-dev libfreetype-dev libgd-dev libjack-dev \
|
||||
libjpeg-dev liblo-dev libmad0-dev libmagic-dev libmp3lame-dev libopus-dev libpng-dev libportaudio2 \
|
||||
libpulse-dev libsamplerate0-dev libsdl2-dev libsdl2-ttf-dev libsdl2-image-dev libshine-dev libsoundtouch-dev libspeex-dev \
|
||||
|
@ -12,7 +11,7 @@ $minimal_apt_get_install libao-dev libasound2-dev libavcodec-dev libavdevice-dev
|
|||
bubblewrap ffmpeg
|
||||
|
||||
# Optional audio plugins
|
||||
$minimal_apt_get_install frei0r-plugins-dev ladspa-sdk multimedia-audio-plugins swh-plugins tap-plugins lsp-plugins-ladspa
|
||||
apt-get install -y --no-install-recommends frei0r-plugins-dev ladspa-sdk multimedia-audio-plugins swh-plugins tap-plugins lsp-plugins-ladspa
|
||||
|
||||
# Per-architecture LS installs
|
||||
ARCHITECTURE=amd64
|
||||
|
@ -30,7 +29,7 @@ rm -f /tmp/liquidsoap.deb
|
|||
ln -s /usr/bin/liquidsoap /usr/local/bin/liquidsoap
|
||||
|
||||
# else
|
||||
# $minimal_apt_get_install build-essential libssl-dev libcurl4-openssl-dev m4 ocaml opam autoconf automake
|
||||
# apt-get install -y --no-install-recommends build-essential libssl-dev libcurl4-openssl-dev m4 ocaml opam autoconf automake
|
||||
# sudo -u azuracast bash /bd_build/stations/liquidsoap/build_as_azuracast.sh
|
||||
# ln -s /var/azuracast/.opam/4.13.1/bin/liquidsoap /usr/local/bin/liquidsoap
|
||||
# chmod a+x /usr/local/bin/liquidsoap
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
# $minimal_apt_get_install python3-minimal python3-pip
|
||||
# pip3 install setuptools supervisor
|
||||
|
||||
$minimal_apt_get_install supervisor
|
||||
|
||||
# mkdir -p /etc/supervisor
|
||||
cp /bd_build/stations/supervisor/supervisord.conf /etc/supervisor/supervisord.conf
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install vorbis-tools
|
||||
apt-get install -y --no-install-recommends vorbis-tools
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
set -x
|
||||
|
||||
apt-get update
|
||||
|
||||
# Install common scripts
|
||||
# cp -rT /bd_build/supervisor/scripts/ /usr/local/bin
|
||||
|
||||
# cp -rT /bd_build/supervisor/startup_scripts/. /etc/my_init.d/
|
||||
|
||||
# cp -rT /bd_build/supervisor/service.minimal/. /etc/supervisor/minimal.conf.d/
|
||||
|
||||
# cp -rT /bd_build/supervisor/service.full/. /etc/supervisor/full.conf.d/
|
||||
|
||||
# Run service setup for all setup scripts
|
||||
for f in /bd_build/supervisor/setup/*.sh; do
|
||||
bash "$f" -H
|
||||
done
|
||||
|
||||
# Cleanup
|
||||
apt-get -y autoremove
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
rm -rf /tmp/tmp*
|
||||
|
||||
chmod -R a+x /usr/local/bin
|
||||
chmod -R +x /etc/my_init.d
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
set -x
|
||||
|
||||
# apt-get install -y --no-install-recommends python3-minimal python3-pip
|
||||
# pip3 install setuptools supervisor
|
||||
|
||||
apt-get install -y --no-install-recommends supervisor
|
||||
|
||||
mkdir -p /etc/supervisor
|
||||
mkdir -p /etc/supervisor/full.conf.d/
|
||||
mkdir -p /etc/supervisor/minimal.conf.d/
|
||||
|
||||
cp /bd_build/supervisor/supervisor/supervisord*.conf /etc/supervisor/
|
|
@ -0,0 +1,2 @@
|
|||
[include]
|
||||
files = supervisord.conf minimal.conf.d/* full.conf.d/* /var/azuracast/stations/*/config/supervisord.conf
|
|
@ -0,0 +1,2 @@
|
|||
[include]
|
||||
files = supervisord.conf minimal.conf.d/*
|
|
@ -10,7 +10,6 @@ logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
|
|||
logfile_backups=10 ; (num of main logfile rotation backups;default 10)
|
||||
loglevel=info ; (log level;default info; others: debug,warn,trace)
|
||||
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
|
||||
nodaemon=true ; (start in foreground if true;default false)
|
||||
minfds=1024 ; (min. avail startup file descriptors;default 1024)
|
||||
minprocs=200 ; (min. avail process descriptors;default 200)
|
||||
|
||||
|
@ -18,7 +17,4 @@ minprocs=200 ; (min. avail process descriptors;default 200)
|
|||
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||
|
||||
[supervisorctl]
|
||||
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
|
||||
|
||||
[include]
|
||||
files = /var/azuracast/stations/*/config/supervisord.conf conf.d/*
|
||||
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
|
|
@ -1,2 +1,4 @@
|
|||
SHELL=/bin/bash
|
||||
BASH_ENV=/container.env
|
||||
* * * * * root /usr/local/bin/cron_task azuracast_cli azuracast:sync:run
|
||||
30 */6 * * * root /usr/local/bin/temp_cleanup
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source /etc/container_environment.sh
|
||||
|
||||
exec azuracast_cli azuracast:internal:sftp-auth "$@"
|
|
@ -1,5 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source /etc/container_environment.sh
|
||||
|
||||
exec azuracast_cli azuracast:internal:sftp-event "$@"
|
|
@ -1,5 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source /etc/container_environment.sh
|
||||
|
||||
exec gosu azuracast "$@" >/proc/1/fd/1 2>/proc/1/fd/2
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [ `whoami` != 'azuracast' ]; then
|
||||
exec gosu azuracast liquidsoap_cli "$@"
|
||||
fi
|
||||
|
||||
source /etc/container_environment.sh
|
||||
|
||||
exec azuracast_cli azuracast:internal:liquidsoap "$@"
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
sv restart nginx
|
||||
supervisorctl restart nginx
|
||||
|
||||
azuracast_cli azuracast:internal:on-ssl-renewal
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
sv -w 45 check nginx || exit 1
|
||||
|
||||
# Acme loading script
|
||||
# Uses code from:
|
||||
# https://github.com/nginx-proxy/acme-companion/blob/main/app/letsencrypt_service
|
||||
|
@ -204,7 +202,7 @@ function update_cert {
|
|||
else
|
||||
# If we did not get any email at all, use the default (empty mail) config
|
||||
config_home="/etc/acme.sh/default"
|
||||
fi
|
||||
fi
|
||||
|
||||
local -n acme_ca_uri="ACME_CA_URI"
|
||||
if [[ -z "$acme_ca_uri" ]]; then
|
||||
|
@ -253,7 +251,7 @@ function update_cert {
|
|||
# We're not using Zero SSL, register the ACME account using the provided email.
|
||||
params_register_arr+=(--accountemail "$accountemail")
|
||||
fi
|
||||
|
||||
|
||||
# Account registration and update if required
|
||||
if [[ ! -f "$account_file" ]]; then
|
||||
params_register_arr=("${params_base_arr[@]}" "${params_register_arr[@]}")
|
||||
|
@ -279,7 +277,7 @@ function update_cert {
|
|||
params_issue_arr+=(--preferred-chain "$acme_preferred_chain")
|
||||
fi
|
||||
if [[ "$RENEW_PRIVATE_KEYS" != 'false' && "$REUSE_PRIVATE_KEYS" != 'true' ]]; then
|
||||
params_issue_arr+=(--always-force-new-domain-key)
|
||||
params_issue_arr+=(--always-force-new-domain-key)
|
||||
fi
|
||||
|
||||
[[ "${2:-}" == "--force-renew" ]] && params_issue_arr+=(--force)
|
|
@ -1,14 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
source /etc/container_environment.sh
|
||||
|
||||
if [ -f /etc/service/mariadb/run ]; then
|
||||
sv -w 30 check mariadb || exit 1
|
||||
fi
|
||||
|
||||
if [ -f /etc/service/redis/run ]; then
|
||||
sv -w 30 check redis || exit 1
|
||||
fi
|
||||
source /etc/php/.version
|
||||
|
||||
# Set up PHP config
|
||||
dockerize -template "/etc/php/${PHP_VERSION}/fpm/05-azuracast.ini.tmpl:/etc/php/${PHP_VERSION}/fpm/conf.d/05-azuracast.ini" \
|
|
@ -0,0 +1,11 @@
|
|||
[program:acme]
|
||||
command=run_acme_sh
|
||||
priority=200
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=true
|
||||
|
||||
stdout_logfile=/proc/1/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/proc/1/fd/2
|
||||
stderr_logfile_maxbytes=0
|
|
@ -0,0 +1,11 @@
|
|||
[program:beanstalkd]
|
||||
command=beanstalkd -p 11300 -z 262140
|
||||
user=azuracast
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=unexpected
|
||||
|
||||
stdout_logfile=/proc/1/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/proc/1/fd/2
|
||||
stderr_logfile_maxbytes=0
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo 'Spinning up Beanstalkd process...'
|
||||
|
||||
exec gosu azuracast beanstalkd -p 11300 -z 262140
|
|
@ -0,0 +1,11 @@
|
|||
[program:cron]
|
||||
command=/usr/sbin/cron -f
|
||||
priority=600
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=unexpected
|
||||
|
||||
stdout_logfile=/proc/1/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/proc/1/fd/2
|
||||
stderr_logfile_maxbytes=0
|
|
@ -0,0 +1,13 @@
|
|||
[program:nginx]
|
||||
command=nginx -g "daemon off;"
|
||||
priority=100
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=unexpected
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
|
||||
stdout_logfile=/proc/1/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/proc/1/fd/2
|
||||
stderr_logfile_maxbytes=0
|
|
@ -0,0 +1,13 @@
|
|||
[program:php-fpm]
|
||||
command=run_php_fpm
|
||||
priority=500
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=unexpected
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
|
||||
stdout_logfile=/proc/1/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/proc/1/fd/2
|
||||
stderr_logfile_maxbytes=0
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
FCGI_CONNECT=/var/run/php-fpm-www.sock exec php-fpm-healthcheck
|
|
@ -0,0 +1,14 @@
|
|||
[program:php-nowplaying]
|
||||
command=php /var/azuracast/www/bin/console azuracast:sync:nowplaying
|
||||
user=azuracast
|
||||
priority=600
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
|
||||
stdout_logfile=/proc/1/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/proc/1/fd/2
|
||||
stderr_logfile_maxbytes=0
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
sv -w 30 check php-fpm || exit 1
|
||||
|
||||
exec gosu azuracast php /var/azuracast/www/bin/console azuracast:sync:nowplaying
|
|
@ -0,0 +1,14 @@
|
|||
[program:php-worker]
|
||||
command=php /var/azuracast/www/bin/console queue:process --worker-name=app_worker_0
|
||||
user=azuracast
|
||||
priority=600
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
|
||||
stdout_logfile=/proc/1/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/proc/1/fd/2
|
||||
stderr_logfile_maxbytes=0
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
sv -w 30 check php-fpm || exit 1
|
||||
|
||||
exec gosu azuracast php /var/azuracast/www/bin/console queue:process --worker-name=app_worker_0
|
|
@ -0,0 +1,15 @@
|
|||
[program:sftpgo]
|
||||
command=sftpgo --config-dir=/var/azuracast/sftpgo serve -l ""
|
||||
dir=/var/azuracast/sftpgo
|
||||
user=azuracast
|
||||
priority=700
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
|
||||
stdout_logfile=/proc/1/fd/1
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/proc/1/fd/2
|
||||
stderr_logfile_maxbytes=0
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
apt-get update
|
||||
|
@ -10,11 +9,20 @@ cp -rT /bd_build/web/scripts/ /usr/local/bin
|
|||
|
||||
cp -rT /bd_build/web/startup_scripts/. /etc/my_init.d/
|
||||
|
||||
# cp -rT /bd_build/web/service.minimal/. /etc/service.minimal/
|
||||
# cp -rT /bd_build/web/service.minimal/. /etc/supervisor/minimal.conf.d/
|
||||
|
||||
cp -rT /bd_build/web/service.full/. /etc/service.full/
|
||||
cp -rT /bd_build/web/service.full/. /etc/supervisor/full.conf.d/
|
||||
|
||||
# Run service setup for all setup scripts
|
||||
for f in /bd_build/web/setup/*.sh; do
|
||||
bash "$f" -H
|
||||
done
|
||||
|
||||
# Cleanup
|
||||
apt-get -y autoremove
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
rm -rf /tmp/tmp*
|
||||
|
||||
chmod -R a+x /usr/local/bin
|
||||
chmod -R +x /etc/my_init.d
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
# Get acme.sh ACME client source
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
add-apt-repository -y ppa:chris-needham/ppa
|
||||
apt-get update
|
||||
|
||||
$minimal_apt_get_install audiowaveform
|
||||
apt-get install -y --no-install-recommends audiowaveform
|
||||
|
|
|
@ -1,8 +1,25 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install netbase
|
||||
install_without_postinst() {
|
||||
local PACKAGE
|
||||
PACKAGE=$1
|
||||
|
||||
mkdir -p /tmp/install_$PACKAGE
|
||||
cd /tmp/install_$PACKAGE
|
||||
|
||||
apt-get download $PACKAGE
|
||||
dpkg --unpack $PACKAGE*.deb
|
||||
rm -f /var/lib/dpkg/info/$PACKAGE.postinst
|
||||
dpkg --configure $PACKAGE
|
||||
|
||||
apt-get install -yf #To fix dependencies
|
||||
|
||||
cd /
|
||||
rm -rf /tmp/install_$PACKAGE
|
||||
}
|
||||
|
||||
apt-get install -y --no-install-recommends netbase
|
||||
|
||||
install_without_postinst beanstalkd
|
||||
|
|
|
@ -1,8 +1,25 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
install_without_postinst() {
|
||||
local PACKAGE
|
||||
PACKAGE=$1
|
||||
|
||||
mkdir -p /tmp/install_$PACKAGE
|
||||
cd /tmp/install_$PACKAGE
|
||||
|
||||
apt-get download $PACKAGE
|
||||
dpkg --unpack $PACKAGE*.deb
|
||||
rm -f /var/lib/dpkg/info/$PACKAGE.postinst
|
||||
dpkg --configure $PACKAGE
|
||||
|
||||
apt-get install -yf #To fix dependencies
|
||||
|
||||
cd /
|
||||
rm -rf /tmp/install_$PACKAGE
|
||||
}
|
||||
|
||||
install_without_postinst cron
|
||||
|
||||
chmod 600 /etc/crontab
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
cd /tmp
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install nginx nginx-common nginx-extras openssl
|
||||
apt-get install -y --no-install-recommends nginx nginx-common nginx-extras openssl
|
||||
|
||||
# Install nginx and configuration
|
||||
cp /bd_build/web/nginx/proxy_params.conf /etc/nginx/proxy_params
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
PHP_VERSION=8.1
|
||||
|
||||
echo "${PHP_VERSION}" >> /etc/container_environment/PHP_VERSION
|
||||
|
||||
add-apt-repository -y ppa:ondrej/php
|
||||
apt-get update
|
||||
|
||||
$minimal_apt_get_install php${PHP_VERSION}-fpm php${PHP_VERSION}-cli php${PHP_VERSION}-gd \
|
||||
apt-get install -y --no-install-recommends php${PHP_VERSION}-fpm php${PHP_VERSION}-cli php${PHP_VERSION}-gd \
|
||||
php${PHP_VERSION}-curl php${PHP_VERSION}-xml php${PHP_VERSION}-zip php${PHP_VERSION}-bcmath \
|
||||
php${PHP_VERSION}-gmp php${PHP_VERSION}-mysqlnd php${PHP_VERSION}-mbstring php${PHP_VERSION}-intl \
|
||||
php${PHP_VERSION}-redis php${PHP_VERSION}-maxminddb php${PHP_VERSION}-xdebug \
|
||||
mariadb-client
|
||||
|
||||
# Copy PHP configuration
|
||||
echo "PHP_VERSION=$PHP_VERSION" >> /etc/php/.version
|
||||
|
||||
mkdir -p /run/php
|
||||
touch /run/php/php${PHP_VERSION}-fpm.pid
|
||||
|
||||
|
@ -27,14 +26,14 @@ cp /bd_build/web/php/www.conf.tmpl /etc/php/${PHP_VERSION}/fpm/www.conf.tmpl
|
|||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer
|
||||
|
||||
# Download PHP-FPM healthcheck script
|
||||
$minimal_apt_get_install libfcgi-bin
|
||||
apt-get install -y --no-install-recommends libfcgi-bin
|
||||
|
||||
wget -O /usr/local/bin/php-fpm-healthcheck \
|
||||
https://raw.githubusercontent.com/renatomefi/php-fpm-healthcheck/master/php-fpm-healthcheck \
|
||||
&& chmod +x /usr/local/bin/php-fpm-healthcheck
|
||||
|
||||
# Install PHP SPX profiler
|
||||
$minimal_apt_get_install php${PHP_VERSION}-dev zlib1g-dev build-essential
|
||||
apt-get install -y --no-install-recommends php${PHP_VERSION}-dev zlib1g-dev build-essential
|
||||
|
||||
cd /bd_build
|
||||
git clone https://github.com/NoiseByNorthwest/php-spx.git
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
add-apt-repository -y ppa:sftpgo/sftpgo
|
||||
apt-get update
|
||||
|
||||
$minimal_apt_get_install sftpgo
|
||||
apt-get install -y --no-install-recommends sftpgo
|
||||
|
||||
mkdir -p /var/azuracast/sftpgo/persist /var/azuracast/sftpgo/backups
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install tmpreaper
|
||||
apt-get install -y --no-install-recommends tmpreaper
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install zstd
|
||||
apt-get install -y --no-install-recommends zstd
|
||||
|
|
|
@ -1,53 +1,53 @@
|
|||
{
|
||||
"common": {
|
||||
"idle_timeout": 15,
|
||||
"upload_mode": 2,
|
||||
"setstat_mode": 1,
|
||||
"actions": {
|
||||
"execute_on": [
|
||||
"upload",
|
||||
"pre-delete",
|
||||
"rename"
|
||||
],
|
||||
"hook": "/usr/local/bin/azuracast_sftp_event"
|
||||
},
|
||||
"defender": {
|
||||
"enabled": true,
|
||||
"driver": "memory"
|
||||
}
|
||||
"common": {
|
||||
"idle_timeout": 15,
|
||||
"upload_mode": 2,
|
||||
"setstat_mode": 1,
|
||||
"actions": {
|
||||
"execute_on": [
|
||||
"upload",
|
||||
"pre-delete",
|
||||
"rename"
|
||||
],
|
||||
"hook": "http://127.0.0.1:6010/api/internal/sftp-event"
|
||||
},
|
||||
"sftpd": {
|
||||
"bindings": [
|
||||
{
|
||||
"port": 2022,
|
||||
"address": "",
|
||||
"apply_proxy_config": true
|
||||
}
|
||||
],
|
||||
"host_keys": [
|
||||
"persist/id_rsa",
|
||||
"persist/id_ecdsa",
|
||||
"persist/id_ed25519"
|
||||
],
|
||||
"enable_scp": true
|
||||
},
|
||||
"httpd": {
|
||||
"bindings": [
|
||||
{
|
||||
"port": 0
|
||||
}
|
||||
],
|
||||
"templates_path": "/usr/share/sftpgo/templates",
|
||||
"static_files_path": "/usr/share/sftpgo/static"
|
||||
},
|
||||
"telemetry": {
|
||||
"bind_port": 0
|
||||
},
|
||||
"data_provider": {
|
||||
"driver": "bolt",
|
||||
"name": "sftpgo.db",
|
||||
"users_base_dir": "/var/azuracast/stations",
|
||||
"external_auth_hook": "/usr/local/bin/azuracast_sftp_auth",
|
||||
"external_auth_scope": 0
|
||||
"defender": {
|
||||
"enabled": true,
|
||||
"driver": "memory"
|
||||
}
|
||||
},
|
||||
"sftpd": {
|
||||
"bindings": [
|
||||
{
|
||||
"port": 2022,
|
||||
"address": "",
|
||||
"apply_proxy_config": true
|
||||
}
|
||||
],
|
||||
"host_keys": [
|
||||
"persist/id_rsa",
|
||||
"persist/id_ecdsa",
|
||||
"persist/id_ed25519"
|
||||
],
|
||||
"enable_scp": true
|
||||
},
|
||||
"httpd": {
|
||||
"bindings": [
|
||||
{
|
||||
"port": 0
|
||||
}
|
||||
],
|
||||
"templates_path": "/usr/share/sftpgo/templates",
|
||||
"static_files_path": "/usr/share/sftpgo/static"
|
||||
},
|
||||
"telemetry": {
|
||||
"bind_port": 0
|
||||
},
|
||||
"data_provider": {
|
||||
"driver": "bolt",
|
||||
"name": "sftpgo.db",
|
||||
"users_base_dir": "/var/azuracast/stations",
|
||||
"external_auth_hook": "http://127.0.0.1:6010/api/internal/sftp-auth",
|
||||
"external_auth_scope": 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
sv -w 30 check php-fpm || exit 1
|
||||
#!/bin/bash
|
||||
|
||||
# Touch cron files to fix 'NUMBER OF HARD LINKS > 1' issue. See https://github.com/phusion/baseimage-docker/issues/198
|
||||
touch -c /var/spool/cron/crontabs/*
|
||||
touch -c /etc/crontab
|
||||
touch -c /etc/cron.*/*
|
||||
|
||||
exec /usr/sbin/cron -f
|
|
@ -1,9 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
sv -w 30 check php-fpm || exit 1
|
||||
|
||||
REDIS_LOCAL=false
|
||||
if [ -f /etc/service/redis/run ]; then
|
||||
if [ -f /etc/supervisor/minimal.conf.d/redis.conf ]; then
|
||||
REDIS_LOCAL=true
|
||||
fi
|
||||
export REDIS_LOCAL
|
||||
|
@ -11,5 +9,3 @@ export REDIS_LOCAL
|
|||
# Copy the nginx template to its destination.
|
||||
dockerize -template "/etc/nginx/nginx.conf.tmpl:/etc/nginx/nginx.conf" \
|
||||
-template "/etc/nginx/azuracast.conf.tmpl:/etc/nginx/sites-available/default"
|
||||
|
||||
exec nginx -g "daemon off;"
|
|
@ -1,7 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo 'Spinning up SFTP process...'
|
||||
|
||||
if [[ ! -f /var/azuracast/sftpgo/persist/id_rsa ]]; then
|
||||
ssh-keygen -t rsa -b 4096 -f /var/azuracast/sftpgo/persist/id_rsa -q -N ""
|
||||
fi
|
||||
|
@ -15,7 +13,3 @@ if [[ ! -f /var/azuracast/sftpgo/persist/id_ed25519 ]]; then
|
|||
fi
|
||||
|
||||
chown -R azuracast:azuracast /var/azuracast/sftpgo/persist
|
||||
|
||||
cd /var/azuracast/sftpgo
|
||||
|
||||
exec sudo -E -u azuracast sftpgo --config-dir=/var/azuracast/sftpgo serve -l "" > /proc/1/fd/1 2> /proc/1/fd/2
|
Loading…
Reference in New Issue