AzuraCast in a Single Docker Image (#5167)
This commit is contained in:
parent
d1ee9db407
commit
27260729bc
|
@ -45,7 +45,7 @@ jobs:
|
|||
uses: actions/cache@v2
|
||||
with:
|
||||
path: vendor
|
||||
key: ${{ runner.OS }}-build-${{ hashFiles('**/composer.lock') }}
|
||||
key: ${{ runner.OS }}-build-${{ hashFiles('composer.lock') }}
|
||||
|
||||
- name: Set console permissions and clear static assets.
|
||||
run: |
|
||||
|
@ -117,8 +117,8 @@ jobs:
|
|||
with:
|
||||
context: .
|
||||
load: true
|
||||
tags: ghcr.io/azuracast/web:latest
|
||||
cache-from: type=registry,ref=ghcr.io/azuracast/web:buildcache
|
||||
tags: ghcr.io/azuracast/azuracast:latest
|
||||
cache-from: type=registry,ref=ghcr.io/azuracast/azuracast:buildcache
|
||||
|
||||
- name: Set up functional test environment.
|
||||
run: |
|
||||
|
@ -126,13 +126,12 @@ jobs:
|
|||
cp azuracast.sample.env azuracast.env
|
||||
cp docker-compose.sample.yml docker-compose.yml
|
||||
cp docker-compose.testing.yml docker-compose.override.yml
|
||||
docker-compose run --rm --user="azuracast" web azuracast_install
|
||||
|
||||
- name: Run functional test suite.
|
||||
run: |
|
||||
chmod 777 tests/_output/
|
||||
chmod 777 tests/_support/_generated
|
||||
docker-compose run --rm --user="azuracast" web composer codeception-no-coverage
|
||||
docker-compose run --rm web azuracast_ci
|
||||
|
||||
- name: Stop all running containers.
|
||||
run: |
|
||||
|
@ -202,8 +201,8 @@ jobs:
|
|||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: |
|
||||
azuracast/azuracast_web_v2
|
||||
ghcr.io/azuracast/web
|
||||
azuracast/azuracast
|
||||
ghcr.io/azuracast/azuracast
|
||||
tags: |
|
||||
type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
|
||||
type=ref,event=branch
|
||||
|
@ -217,5 +216,5 @@ jobs:
|
|||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=ghcr.io/azuracast/web:buildcache
|
||||
cache-to: type=registry,ref=ghcr.io/azuracast/web:buildcache,mode=max
|
||||
cache-from: type=registry,ref=ghcr.io/azuracast/azuracast:buildcache
|
||||
cache-to: type=registry,ref=ghcr.io/azuracast/azuracast:buildcache,mode=max
|
||||
|
|
59
Dockerfile
59
Dockerfile
|
@ -1,3 +1,11 @@
|
|||
#
|
||||
# Icecast build stage (for later copy)
|
||||
#
|
||||
FROM ghcr.io/azuracast/icecast-kh-ac:2.4.0-kh15-ac2 AS icecast
|
||||
|
||||
#
|
||||
# Golang dependencies build step
|
||||
#
|
||||
FROM golang:1.17-buster AS dockerize
|
||||
|
||||
RUN apt-get update \
|
||||
|
@ -5,22 +13,49 @@ RUN apt-get update \
|
|||
|
||||
RUN go install github.com/jwilder/dockerize@latest
|
||||
|
||||
#
|
||||
# Final build image
|
||||
FROM ubuntu:focal
|
||||
#
|
||||
FROM mariadb:10.5-focal
|
||||
|
||||
ENV TZ="UTC"
|
||||
|
||||
# Add Dockerize
|
||||
COPY --from=dockerize /go/bin/dockerize /usr/local/bin
|
||||
|
||||
# Run base build process
|
||||
COPY ./util/docker/web /bd_build/
|
||||
# Import Icecast-KH from build container
|
||||
COPY --from=icecast /usr/local/bin/icecast /usr/local/bin/icecast
|
||||
COPY --from=icecast /usr/local/share/icecast /usr/local/share/icecast
|
||||
|
||||
# Run base build process
|
||||
COPY ./util/docker/common /bd_build/
|
||||
RUN chmod a+x /bd_build/*.sh \
|
||||
&& /bd_build/prepare.sh \
|
||||
&& /bd_build/add_user.sh \
|
||||
&& /bd_build/setup.sh \
|
||||
&& /bd_build/cleanup.sh \
|
||||
&& /bd_build/cleanup.sh
|
||||
|
||||
# Build each set of dependencies in their own step for cacheability.
|
||||
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
|
||||
|
||||
#
|
||||
|
@ -42,7 +77,8 @@ COPY --chown=azuracast:azuracast . .
|
|||
RUN composer dump-autoload --optimize --classmap-authoritative \
|
||||
&& touch /var/azuracast/.docker
|
||||
|
||||
VOLUME ["/var/azuracast/www_tmp", "/var/azuracast/uploads", "/var/azuracast/backups", "/var/azuracast/sftpgo/persist"]
|
||||
VOLUME ["/var/azuracast/stations", "/var/azuracast/www_tmp", "/var/azuracast/uploads", "/var/azuracast/backups", "/var/azuracast/sftpgo/persist", "/var/azuracast/servers/shoutcast2"]
|
||||
ENV PATH="${PATH}:/var/azuracast/servers/shoutcast2"
|
||||
|
||||
#
|
||||
# END Operations as `azuracast` user
|
||||
|
@ -50,18 +86,19 @@ VOLUME ["/var/azuracast/www_tmp", "/var/azuracast/uploads", "/var/azuracast/back
|
|||
USER root
|
||||
|
||||
EXPOSE 80 2022
|
||||
EXPOSE 8000-8999
|
||||
|
||||
# Sensible default environment variables.
|
||||
ENV LANG="en_US.UTF-8" \
|
||||
DOCKER_IS_STANDALONE="true" \
|
||||
APPLICATION_ENV="production" \
|
||||
ENABLE_ADVANCED_FEATURES="false" \
|
||||
MYSQL_HOST="mariadb" \
|
||||
MYSQL_HOST="localhost" \
|
||||
MYSQL_PORT=3306 \
|
||||
MYSQL_USER="azuracast" \
|
||||
MYSQL_PASSWORD="azur4c457" \
|
||||
MYSQL_DATABASE="azuracast" \
|
||||
ENABLE_REDIS="true" \
|
||||
REDIS_HOST="redis" \
|
||||
REDIS_HOST="localhost" \
|
||||
REDIS_PORT=6379 \
|
||||
REDIS_DB=1 \
|
||||
NGINX_RADIO_PORTS="default" \
|
||||
|
@ -75,5 +112,5 @@ ENV LANG="en_US.UTF-8" \
|
|||
PROFILING_EXTENSION_HTTP_IP_WHITELIST=*
|
||||
|
||||
# Entrypoint and default command
|
||||
ENTRYPOINT ["/usr/local/bin/uptime_wait"]
|
||||
CMD ["/usr/local/bin/my_init"]
|
||||
ENTRYPOINT ["/usr/local/bin/my_init"]
|
||||
CMD ["--no-main-command"]
|
||||
|
|
4
Makefile
4
Makefile
|
@ -26,8 +26,8 @@ build: # Rebuild all containers and restart
|
|||
update: # Update everything (i.e. after a branch update)
|
||||
docker-compose build
|
||||
$(MAKE) down
|
||||
docker-compose run --rm --user=azuracast web composer install
|
||||
docker-compose run --rm --user=azuracast web azuracast_cli azuracast:setup:initialize
|
||||
docker-compose run --rm web gosu azuracast composer install
|
||||
docker-compose run --rm web azuracast_cli azuracast:setup:initialize
|
||||
$(MAKE) frontend-build
|
||||
$(MAKE) up
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
APPLICATION_ENV=development
|
||||
LOG_LEVEL=debug
|
||||
ENABLE_ADVANCED_FEATURES=true
|
||||
COMPOSER_PLUGIN_MODE=false
|
||||
|
||||
# Limit station port range
|
||||
|
|
|
@ -39,17 +39,17 @@ AUTO_ASSIGN_PORT_MAX=8499
|
|||
|
||||
# The host to connect to. Leave this as the default value unless you're connecting
|
||||
# to an external database server.
|
||||
# Default: mariadb
|
||||
MYSQL_HOST=mariadb
|
||||
# Default: localhost
|
||||
# MYSQL_HOST=localhost
|
||||
|
||||
# The port to connect to. Leave this as the default value unless you're connecting
|
||||
# to an external database server.
|
||||
# Default: 3306
|
||||
MYSQL_PORT=3306
|
||||
# MYSQL_PORT=3306
|
||||
|
||||
# The username AzuraCast will use to connect to the database.
|
||||
# Default: azuracast
|
||||
MYSQL_USER=azuracast
|
||||
# MYSQL_USER=azuracast
|
||||
|
||||
# The password AzuraCast will use to connect to the database.
|
||||
# By default, the database is not exposed to the Internet at all and this is only
|
||||
|
@ -59,7 +59,7 @@ MYSQL_PASSWORD=azur4c457
|
|||
|
||||
# The name of the AzuraCast database.
|
||||
# Default: azuracast
|
||||
MYSQL_DATABASE=azuracast
|
||||
# MYSQL_DATABASE=azuracast
|
||||
|
||||
# Automatically generate a random root password upon the first database spin-up.
|
||||
# This password will be visible in the mariadb container's logs.
|
||||
|
@ -71,12 +71,12 @@ MYSQL_RANDOM_ROOT_PASSWORD=yes
|
|||
# To read the slow query log once enabled, run:
|
||||
# docker-compose exec mariadb slow_queries
|
||||
# Default: 0
|
||||
MYSQL_SLOW_QUERY_LOG=0
|
||||
# MYSQL_SLOW_QUERY_LOG=0
|
||||
|
||||
# Set the amount of allowed connections to the database. This value should be increased
|
||||
# if you are seeing the `Too many connections` error in the logs.
|
||||
# Default: 100
|
||||
MYSQL_MAX_CONNECTIONS=100
|
||||
# MYSQL_MAX_CONNECTIONS=100
|
||||
|
||||
#
|
||||
# Redis Configuration
|
||||
|
@ -90,8 +90,8 @@ MYSQL_MAX_CONNECTIONS=100
|
|||
# ENABLE_REDIS=true
|
||||
|
||||
# Name of the Redis host.
|
||||
# Default: redis
|
||||
# REDIS_HOST=redis
|
||||
# Default: localhost
|
||||
# REDIS_HOST=localhost
|
||||
|
||||
# Port to connect to on the Redis host.
|
||||
# Default: 6379
|
||||
|
|
|
@ -92,8 +92,10 @@ class UptimeWait
|
|||
protected function checkDatabase(): bool
|
||||
{
|
||||
try {
|
||||
$defaultHost = $this->isStandalone() ? 'localhost' : 'mariadb';
|
||||
|
||||
$dbOptions = [
|
||||
'host' => $_ENV['MYSQL_HOST'] ?? 'mariadb',
|
||||
'host' => $_ENV['MYSQL_HOST'] ?? $defaultHost,
|
||||
'port' => (int)($_ENV['MYSQL_PORT'] ?? 3306),
|
||||
'dbname' => $_ENV['MYSQL_DATABASE'] ?? 'azuracast',
|
||||
'user' => $_ENV['MYSQL_USER'] ?? 'azuracast',
|
||||
|
@ -119,8 +121,10 @@ class UptimeWait
|
|||
|
||||
protected function checkRedis(): bool
|
||||
{
|
||||
$defaultHost = $this->isStandalone() ? 'localhost' : 'redis';
|
||||
|
||||
$enableRedis = $this->envToBool($_ENV['ENABLE_REDIS'] ?? true);
|
||||
$redisHost = $_ENV['REDIS_HOST'] ?? 'redis';
|
||||
$redisHost = $_ENV['REDIS_HOST'] ?? $defaultHost;
|
||||
$redisPort = (int)($_ENV['REDIS_PORT'] ?? 6379);
|
||||
$redisDb = (int)($_ENV['REDIS_DB'] ?? 1);
|
||||
|
||||
|
@ -157,6 +161,11 @@ class UptimeWait
|
|||
|| '1' === $value;
|
||||
}
|
||||
|
||||
protected function isStandalone(): bool
|
||||
{
|
||||
return $this->envToBool($_ENV['DOCKER_IS_STANDALONE'] ?? false);
|
||||
}
|
||||
|
||||
protected function println(string $line): void
|
||||
{
|
||||
echo $line . "\n";
|
||||
|
|
|
@ -1,28 +1,13 @@
|
|||
services :
|
||||
web :
|
||||
build :
|
||||
context : .
|
||||
volumes :
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
ports:
|
||||
- "127.0.0.1:3306:3306"
|
||||
- "127.0.0.1:6379:6379"
|
||||
volumes:
|
||||
- ./util/local_ssl:/etc/nginx/certs
|
||||
- ./vendor:/var/azuracast/www/vendor
|
||||
- .:/var/azuracast/www
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
mariadb :
|
||||
build :
|
||||
context : ../docker-azuracast-db
|
||||
ports :
|
||||
- "127.0.0.1:3306:3306"
|
||||
|
||||
redis :
|
||||
build :
|
||||
context : ../docker-azuracast-redis
|
||||
ports :
|
||||
- "127.0.0.1:6379:6379"
|
||||
|
||||
stations :
|
||||
build :
|
||||
context : ../docker-azuracast-radio
|
||||
volumes :
|
||||
- ./util/local_ssl:/etc/nginx/certs
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
services :
|
||||
installer :
|
||||
container_name : azuracast_installer
|
||||
image : 'ghcr.io/azuracast/web:${AZURACAST_VERSION:-latest}'
|
||||
volumes :
|
||||
container_name: azuracast_installer
|
||||
image: 'ghcr.io/azuracast/web:${AZURACAST_VERSION:-latest}'
|
||||
volumes:
|
||||
- './:/installer'
|
||||
restart : 'no'
|
||||
user : root
|
||||
entrypoint : docker_installer
|
||||
command : install
|
||||
restart: 'no'
|
||||
user: root
|
||||
entrypoint: minimal_init
|
||||
command: docker_installer install
|
||||
|
|
|
@ -12,83 +12,14 @@
|
|||
|
||||
services:
|
||||
web:
|
||||
container_name: azuracast_web
|
||||
image: "ghcr.io/azuracast/web:${AZURACAST_VERSION:-latest}"
|
||||
container_name: azuracast
|
||||
image: "ghcr.io/azuracast/azuracast:${AZURACAST_VERSION:-latest}"
|
||||
# Want to customize the HTTP/S ports? Follow the instructions here:
|
||||
# https://docs.azuracast.com/en/administration/docker#using-non-standard-ports
|
||||
ports:
|
||||
- '${AZURACAST_HTTP_PORT:-80}:80'
|
||||
- '${AZURACAST_HTTPS_PORT:-443}:443'
|
||||
- '${AZURACAST_SFTP_PORT:-2022}:2022'
|
||||
depends_on:
|
||||
- mariadb
|
||||
- stations
|
||||
- redis
|
||||
env_file: azuracast.env
|
||||
environment:
|
||||
LANG: ${LANG:-en_US.UTF-8}
|
||||
AZURACAST_DC_REVISION: 13
|
||||
AZURACAST_VERSION: ${AZURACAST_VERSION:-latest}
|
||||
AZURACAST_SFTP_PORT: ${AZURACAST_SFTP_PORT:-2022}
|
||||
NGINX_TIMEOUT: ${NGINX_TIMEOUT:-1800}
|
||||
LETSENCRYPT_HOST: ${LETSENCRYPT_HOST:-}
|
||||
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL:-}
|
||||
PUID: ${AZURACAST_PUID:-1000}
|
||||
PGID: ${AZURACAST_PGID:-1000}
|
||||
volumes:
|
||||
- letsencrypt:/etc/nginx/certs
|
||||
- letsencrypt_acme:/etc/acme.sh
|
||||
- www_vendor:/var/azuracast/www/vendor
|
||||
- www_uploads:/var/azuracast/uploads
|
||||
- tmp_data:/var/azuracast/www_tmp
|
||||
- station_data:/var/azuracast/stations
|
||||
- shoutcast2_install:/var/azuracast/servers/shoutcast2
|
||||
- geolite_install:/var/azuracast/geoip
|
||||
- sftpgo_data:/var/azuracast/sftpgo/persist
|
||||
- backups:/var/azuracast/backups
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
ulimits: &default-ulimits
|
||||
nofile:
|
||||
soft: 65536
|
||||
hard: 65536
|
||||
logging: &default-logging
|
||||
options:
|
||||
max-size: "1m"
|
||||
max-file: "5"
|
||||
|
||||
mariadb:
|
||||
container_name: azuracast_mariadb
|
||||
image: "ghcr.io/azuracast/db:${AZURACAST_VERSION:-latest}"
|
||||
volumes:
|
||||
- db_data:/var/lib/mysql
|
||||
env_file: azuracast.env
|
||||
networks:
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
|
||||
redis:
|
||||
container_name: azuracast_redis
|
||||
image: "ghcr.io/azuracast/redis:${AZURACAST_VERSION:-latest}"
|
||||
sysctls:
|
||||
net.core.somaxconn: 1024
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
networks:
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
|
||||
stations:
|
||||
container_name: azuracast_stations
|
||||
image: "ghcr.io/azuracast/radio:${AZURACAST_VERSION:-latest}"
|
||||
environment:
|
||||
PUID: ${AZURACAST_PUID:-1000}
|
||||
PGID: ${AZURACAST_PGID:-1000}
|
||||
ports:
|
||||
# This default mapping is the outgoing and incoming ports for the first 50 stations.
|
||||
# You can override this port mapping in your own docker-compose.override.yml file.
|
||||
# For instructions, see:
|
||||
|
@ -240,24 +171,38 @@ services:
|
|||
- '8490:8490'
|
||||
- '8495:8495'
|
||||
- '8496:8496'
|
||||
env_file: azuracast.env
|
||||
environment:
|
||||
LANG: ${LANG:-en_US.UTF-8}
|
||||
AZURACAST_DC_REVISION: 14
|
||||
AZURACAST_VERSION: ${AZURACAST_VERSION:-latest}
|
||||
AZURACAST_SFTP_PORT: ${AZURACAST_SFTP_PORT:-2022}
|
||||
NGINX_TIMEOUT: ${NGINX_TIMEOUT:-1800}
|
||||
LETSENCRYPT_HOST: ${LETSENCRYPT_HOST:-}
|
||||
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL:-}
|
||||
PUID: ${AZURACAST_PUID:-1000}
|
||||
PGID: ${AZURACAST_PGID:-1000}
|
||||
volumes:
|
||||
- letsencrypt:/etc/nginx/certs
|
||||
- letsencrypt_acme:/etc/acme.sh
|
||||
- www_vendor:/var/azuracast/www/vendor
|
||||
- www_uploads:/var/azuracast/uploads
|
||||
- tmp_data:/var/azuracast/www_tmp
|
||||
- station_data:/var/azuracast/stations
|
||||
- shoutcast2_install:/var/azuracast/servers/shoutcast2
|
||||
- letsencrypt:/etc/nginx/certs
|
||||
- tmp_data:/var/azuracast/www_tmp
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
init: true
|
||||
- geolite_install:/var/azuracast/geoip
|
||||
- sftpgo_data:/var/azuracast/sftpgo/persist
|
||||
- backups:/var/azuracast/backups
|
||||
- db_data:/var/lib/mysql
|
||||
restart: unless-stopped
|
||||
ulimits: *default-ulimits
|
||||
logging: *default-logging
|
||||
|
||||
networks:
|
||||
frontend:
|
||||
driver: bridge
|
||||
backend:
|
||||
driver: bridge
|
||||
ulimits: &default-ulimits
|
||||
nofile:
|
||||
soft: 65536
|
||||
hard: 65536
|
||||
logging: &default-logging
|
||||
options:
|
||||
max-size: "1m"
|
||||
max-file: "5"
|
||||
|
||||
volumes:
|
||||
db_data: { }
|
||||
|
@ -270,5 +215,4 @@ volumes:
|
|||
www_vendor: { }
|
||||
www_uploads: { }
|
||||
tmp_data: { }
|
||||
redis_data: { }
|
||||
backups: { }
|
||||
|
|
15
docker.sh
15
docker.sh
|
@ -378,6 +378,7 @@ run-installer() {
|
|||
fi
|
||||
|
||||
curl -fsSL https://raw.githubusercontent.com/AzuraCast/AzuraCast/$AZURACAST_RELEASE_BRANCH/docker-compose.installer.yml -o docker-compose.installer.yml
|
||||
|
||||
docker-compose -p azuracast_installer -f docker-compose.installer.yml pull
|
||||
docker-compose -p azuracast_installer -f docker-compose.installer.yml run --rm installer install "$@"
|
||||
|
||||
|
@ -454,14 +455,6 @@ install-dev() {
|
|||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -d ../docker-azuracast-radio ]]; then
|
||||
if ask "Clone related repositories?" Y; then
|
||||
git clone https://github.com/AzuraCast/docker-azuracast-db.git ../docker-azuracast-db
|
||||
git clone https://github.com/AzuraCast/docker-azuracast-redis.git ../docker-azuracast-redis
|
||||
git clone https://github.com/AzuraCast/docker-azuracast-radio.git ../docker-azuracast-radio
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -f docker-compose.yml ]]; then
|
||||
cp docker-compose.sample.yml docker-compose.yml
|
||||
fi
|
||||
|
@ -485,7 +478,7 @@ install-dev() {
|
|||
fi
|
||||
|
||||
docker-compose build
|
||||
docker-compose run --rm --user="azuracast" web azuracast_install "$@"
|
||||
docker-compose run --rm web azuracast_install "$@"
|
||||
|
||||
docker-compose -f frontend/docker-compose.yml build
|
||||
docker-compose -f frontend/docker-compose.yml run --rm frontend npm run dev-build
|
||||
|
@ -563,7 +556,7 @@ update() {
|
|||
docker volume rm azuracast_tmp_data
|
||||
docker volume rm azuracast_redis_data
|
||||
|
||||
docker-compose run --rm --user="azuracast" web azuracast_update "$@"
|
||||
docker-compose run --rm web azuracast_update "$@"
|
||||
docker-compose up -d
|
||||
|
||||
if ask "Clean up all stopped Docker containers and images to save space?" Y; then
|
||||
|
@ -654,7 +647,7 @@ backup() {
|
|||
.env --file .env set AZURACAST_PGID="$(id -g)"
|
||||
fi
|
||||
|
||||
docker-compose run --rm web azuracast_cli azuracast:backup "/var/azuracast/backups/${BACKUP_FILENAME}" "$@"
|
||||
docker-compose exec web azuracast_cli azuracast:backup "/var/azuracast/backups/${BACKUP_FILENAME}" "$@"
|
||||
|
||||
# Move from Docker volume to local filesystem
|
||||
docker run --rm -v "azuracast_backups:/backup_src" \
|
||||
|
|
|
@ -34,6 +34,7 @@ class Environment
|
|||
public const ASSET_URL = 'ASSETS_URL';
|
||||
|
||||
public const DOCKER_REVISION = 'AZURACAST_DC_REVISION';
|
||||
public const DOCKER_IS_STANDALONE = 'DOCKER_IS_STANDALONE';
|
||||
|
||||
public const LANG = 'LANG';
|
||||
|
||||
|
@ -208,22 +209,32 @@ class Environment
|
|||
return ($compareVersion >= $version);
|
||||
}
|
||||
|
||||
public function getUriToWeb(): UriInterface
|
||||
public function isDockerStandalone(): bool
|
||||
{
|
||||
if ($this->isDocker()) {
|
||||
return $this->isDockerRevisionAtLeast(5)
|
||||
? new Uri('http://web')
|
||||
: new Uri('http://nginx');
|
||||
if (!$this->isDocker()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return new Uri('http://127.0.0.1');
|
||||
return self::envToBool($this->data[self::DOCKER_IS_STANDALONE] ?? false);
|
||||
}
|
||||
|
||||
public function getUriToWeb(): UriInterface
|
||||
{
|
||||
return match (true) {
|
||||
$this->isDockerStandalone() => new Uri('http://127.0.0.1'),
|
||||
$this->isDockerRevisionAtLeast(5) => new Uri('http://web'),
|
||||
$this->isDocker() => new Uri('http://nginx'),
|
||||
default => new Uri('http://127.0.0.1')
|
||||
};
|
||||
}
|
||||
|
||||
public function getUriToStations(): UriInterface
|
||||
{
|
||||
return $this->isDocker()
|
||||
? new Uri('http://stations')
|
||||
: new Uri('http://127.0.0.1');
|
||||
return match (true) {
|
||||
$this->isDockerStandalone() => new Uri('http://127.0.0.1'),
|
||||
$this->isDocker() => new Uri('http://stations'),
|
||||
default => new Uri('http://127.0.0.1'),
|
||||
};
|
||||
}
|
||||
|
||||
public function getLang(): ?string
|
||||
|
@ -296,11 +307,17 @@ class Environment
|
|||
*/
|
||||
public function getDatabaseSettings(): array
|
||||
{
|
||||
$defaultHost = match (true) {
|
||||
$this->isDockerStandalone() => 'localhost',
|
||||
$this->isDocker() => 'mariadb',
|
||||
default => 'localhost'
|
||||
};
|
||||
|
||||
return [
|
||||
'host' => $this->data[self::DB_HOST] ?? ($this->isDocker() ? 'mariadb' : 'localhost'),
|
||||
'port' => (int)($this->data[self::DB_PORT] ?? 3306),
|
||||
'dbname' => $this->data[self::DB_NAME] ?? 'azuracast',
|
||||
'user' => $this->data[self::DB_USER] ?? 'azuracast',
|
||||
'host' => $this->data[self::DB_HOST] ?? $defaultHost,
|
||||
'port' => (int)($this->data[self::DB_PORT] ?? 3306),
|
||||
'dbname' => $this->data[self::DB_NAME] ?? 'azuracast',
|
||||
'user' => $this->data[self::DB_USER] ?? 'azuracast',
|
||||
'password' => $this->data[self::DB_PASSWORD] ?? 'azur4c457',
|
||||
];
|
||||
}
|
||||
|
@ -315,10 +332,16 @@ class Environment
|
|||
*/
|
||||
public function getRedisSettings(): array
|
||||
{
|
||||
$defaultHost = match (true) {
|
||||
$this->isDockerStandalone() => 'localhost',
|
||||
$this->isDocker() => 'redis',
|
||||
default => 'localhost'
|
||||
};
|
||||
|
||||
return [
|
||||
'host' => $this->data[self::REDIS_HOST] ?? ($this->isDocker() ? 'redis' : 'localhost'),
|
||||
'host' => $this->data[self::REDIS_HOST] ?? $defaultHost,
|
||||
'port' => (int)($this->data[self::REDIS_PORT] ?? 6379),
|
||||
'db' => (int)($this->data[self::REDIS_DB] ?? 1),
|
||||
'db' => (int)($this->data[self::REDIS_DB] ?? 1),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -337,6 +360,15 @@ class Environment
|
|||
return $this->data[self::PROFILING_EXTENSION_HTTP_KEY] ?? 'dev';
|
||||
}
|
||||
|
||||
public static function getDefaultsForEnvironment(Environment $existingEnv): self
|
||||
{
|
||||
return new self([
|
||||
self::IS_CLI => $existingEnv->isCli(),
|
||||
self::IS_DOCKER => $existingEnv->isDocker(),
|
||||
self::DOCKER_IS_STANDALONE => $existingEnv->isDockerStandalone(),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function envToBool(mixed $value): bool
|
||||
{
|
||||
if (is_bool($value)) {
|
||||
|
|
|
@ -102,11 +102,11 @@ class InstallCommand extends Command
|
|||
$locale = SupportedLocales::getValidLocale($azuracastEnv[Environment::LANG] ?? null);
|
||||
$locale->register($this->environment);
|
||||
|
||||
$envConfig = EnvFile::getConfiguration();
|
||||
$env->setFromDefaults();
|
||||
$envConfig = EnvFile::getConfiguration($this->environment);
|
||||
$env->setFromDefaults($this->environment);
|
||||
|
||||
$azuracastEnvConfig = AzuraCastEnvFile::getConfiguration();
|
||||
$azuracastEnv->setFromDefaults();
|
||||
$azuracastEnvConfig = AzuraCastEnvFile::getConfiguration($this->environment);
|
||||
$azuracastEnv->setFromDefaults($this->environment);
|
||||
|
||||
// Apply values passed via flags
|
||||
if (null !== $releaseChannel) {
|
||||
|
@ -156,6 +156,16 @@ class InstallCommand extends Command
|
|||
$azuracastEnv['MYSQL_RANDOM_ROOT_PASSWORD'] = 'yes';
|
||||
}
|
||||
|
||||
// Special fixes for transitioning to standalone installations.
|
||||
if ($this->environment->isDockerStandalone()) {
|
||||
if ('mariadb' === $azuracastEnv['MYSQL_HOST']) {
|
||||
unset($azuracastEnv['MYSQL_HOST']);
|
||||
}
|
||||
if ('redis' === $azuracastEnv['REDIS_HOST']) {
|
||||
unset($azuracastEnv['REDIS_HOST']);
|
||||
}
|
||||
}
|
||||
|
||||
// Display header messages
|
||||
if ($isNewInstall) {
|
||||
$io->title(
|
||||
|
@ -253,8 +263,8 @@ class InstallCommand extends Command
|
|||
__('Writing configuration files...')
|
||||
);
|
||||
|
||||
$envStr = $env->writeToFile();
|
||||
$azuracastEnvStr = $azuracastEnv->writeToFile();
|
||||
$envStr = $env->writeToFile($this->environment);
|
||||
$azuracastEnvStr = $azuracastEnv->writeToFile($this->environment);
|
||||
|
||||
if ($io->isVerbose()) {
|
||||
$io->section($env->getBasename());
|
||||
|
@ -289,10 +299,12 @@ class InstallCommand extends Command
|
|||
$sampleFile = $this->environment->getBaseDirectory() . '/docker-compose.sample.yml';
|
||||
$yaml = Yaml::parseFile($sampleFile);
|
||||
|
||||
$isStandalone = $this->environment->isDockerStandalone();
|
||||
|
||||
// Parse port listing and convert into YAML format.
|
||||
$ports = $env['AZURACAST_STATION_PORTS'] ?? '';
|
||||
|
||||
$envConfig = $env::getConfiguration();
|
||||
$envConfig = $env::getConfiguration($this->environment);
|
||||
$defaultPorts = $envConfig['AZURACAST_STATION_PORTS']['default'];
|
||||
|
||||
if (!empty($ports) && 0 !== strcmp($ports, $defaultPorts)) {
|
||||
|
@ -316,7 +328,18 @@ class InstallCommand extends Command
|
|||
}
|
||||
|
||||
if (!empty($yamlPorts)) {
|
||||
$yaml['services']['stations']['ports'] = $yamlPorts;
|
||||
if ($isStandalone) {
|
||||
$existingPorts = [];
|
||||
foreach ($yaml['services']['ports'] as $port) {
|
||||
if (str_starts_with('$', $port)) {
|
||||
$existingPorts[] = $port;
|
||||
}
|
||||
}
|
||||
|
||||
$yaml['services']['web']['ports'] = array_merge($existingPorts, $yamlPorts);
|
||||
} else {
|
||||
$yaml['services']['stations']['ports'] = $yamlPorts;
|
||||
}
|
||||
}
|
||||
if (!empty($nginxRadioPorts)) {
|
||||
$nginxRadioPortsStr = '(' . implode('|', $nginxRadioPorts) . ')';
|
||||
|
@ -329,9 +352,11 @@ class InstallCommand extends Command
|
|||
}
|
||||
|
||||
// Remove Redis if it's not enabled.
|
||||
$enableRedis = $azuracastEnv->getAsBool(Environment::ENABLE_REDIS, true);
|
||||
if (!$enableRedis) {
|
||||
unset($yaml['services']['redis']);
|
||||
if (!$isStandalone) {
|
||||
$enableRedis = $azuracastEnv->getAsBool(Environment::ENABLE_REDIS, true);
|
||||
if (!$enableRedis) {
|
||||
unset($yaml['services']['redis']);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove privileged-mode settings if not enabled.
|
||||
|
|
|
@ -32,12 +32,12 @@ abstract class AbstractEnvFile implements ArrayAccess
|
|||
return basename($this->path);
|
||||
}
|
||||
|
||||
public function setFromDefaults(): void
|
||||
public function setFromDefaults(Environment $environment): void
|
||||
{
|
||||
$currentVars = array_filter($this->data);
|
||||
|
||||
$defaults = [];
|
||||
foreach (static::getConfiguration() as $key => $keyInfo) {
|
||||
foreach (static::getConfiguration($environment) as $key => $keyInfo) {
|
||||
if (isset($keyInfo['default'])) {
|
||||
$defaults[$key] = $keyInfo['default'] ?? null;
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ abstract class AbstractEnvFile implements ArrayAccess
|
|||
unset($this->data[$offset]);
|
||||
}
|
||||
|
||||
public function writeToFile(): string
|
||||
public function writeToFile(Environment $environment): string
|
||||
{
|
||||
$values = array_filter($this->data);
|
||||
|
||||
|
@ -93,7 +93,7 @@ abstract class AbstractEnvFile implements ArrayAccess
|
|||
'',
|
||||
];
|
||||
|
||||
foreach (static::getConfiguration() as $key => $keyInfo) {
|
||||
foreach (static::getConfiguration($environment) as $key => $keyInfo) {
|
||||
$envFile[] = '# ' . ($keyInfo['name'] ?? $key);
|
||||
|
||||
if (!empty($keyInfo['description'])) {
|
||||
|
@ -180,7 +180,7 @@ abstract class AbstractEnvFile implements ArrayAccess
|
|||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
abstract public static function getConfiguration(): array;
|
||||
abstract public static function getConfiguration(Environment $environment): array;
|
||||
|
||||
abstract public static function buildPathFromBase(string $baseDir): string;
|
||||
|
||||
|
|
|
@ -14,12 +14,12 @@ use function __;
|
|||
class AzuraCastEnvFile extends AbstractEnvFile
|
||||
{
|
||||
/** @inheritDoc */
|
||||
public static function getConfiguration(): array
|
||||
public static function getConfiguration(Environment $environment): array
|
||||
{
|
||||
static $config = null;
|
||||
|
||||
if (null === $config) {
|
||||
$emptyEnv = new Environment([]);
|
||||
$emptyEnv = Environment::getDefaultsForEnvironment($environment);
|
||||
$defaults = $emptyEnv->toArray();
|
||||
|
||||
$langOptions = [];
|
||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Installer\EnvFiles;
|
||||
|
||||
use App\Environment;
|
||||
use App\Radio\Configuration;
|
||||
|
||||
use function __;
|
||||
|
@ -11,7 +12,7 @@ use function __;
|
|||
class EnvFile extends AbstractEnvFile
|
||||
{
|
||||
/** @inheritDoc */
|
||||
public static function getConfiguration(): array
|
||||
public static function getConfiguration(Environment $environment): array
|
||||
{
|
||||
static $config = null;
|
||||
|
||||
|
|
|
@ -125,7 +125,11 @@ class ConfigWriter implements EventSubscriberInterface
|
|||
$configDir = $station->getRadioConfigDir();
|
||||
$pidfile = $configDir . DIRECTORY_SEPARATOR . 'liquidsoap.pid';
|
||||
|
||||
$telnetBindAddr = $this->environment->isDocker() ? '0.0.0.0' : '127.0.0.1';
|
||||
$telnetBindAddr = match (true) {
|
||||
$this->environment->isDockerStandalone() => '127.0.0.1',
|
||||
$this->environment->isDocker() => '0.0.0.0',
|
||||
default => '127.0.0.1',
|
||||
};
|
||||
$telnetPort = $this->liquidsoap->getTelnetPort($station);
|
||||
|
||||
$stationTz = self::cleanUpString($station->getTimezone());
|
||||
|
|
|
@ -13,7 +13,8 @@ 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/backups /var/azuracast/www_tmp \
|
||||
mkdir -p /var/azuracast/www /var/azuracast/stations /var/azuracast/servers/shoutcast2 \
|
||||
/var/azuracast/backups /var/azuracast/www_tmp \
|
||||
/var/azuracast/uploads /var/azuracast/geoip /var/azuracast/dbip
|
||||
|
||||
chown -R azuracast:azuracast /var/azuracast
|
|
@ -0,0 +1,16 @@
|
|||
#!/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
|
|
@ -67,4 +67,14 @@ 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/
|
||||
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
|
||||
|
||||
# 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/
|
|
@ -30,41 +30,33 @@ terminated_child_processes = {}
|
|||
|
||||
_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
|
||||
|
||||
|
||||
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)
|
||||
|
@ -75,14 +67,12 @@ def 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
|
||||
|
@ -101,7 +91,6 @@ def import_envvars(clear_existing_environment=True, override_existing_environmen
|
|||
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
|
||||
|
@ -118,7 +107,6 @@ def export_envvars(to_dir=True):
|
|||
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:
|
||||
|
@ -130,16 +118,13 @@ def shquote(s):
|
|||
# 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
|
||||
|
||||
|
@ -172,7 +157,6 @@ def waitpid_reap_other_children(pid):
|
|||
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:
|
||||
|
@ -198,7 +182,6 @@ def stop_child_process(name, pid, signo=signal.SIGTERM, time_limit=KILL_PROCESS_
|
|||
finally:
|
||||
signal.alarm(0)
|
||||
|
||||
|
||||
def run_command_killable(*argv):
|
||||
filename = argv[0]
|
||||
status = None
|
||||
|
@ -216,13 +199,11 @@ def run_command_killable(*argv):
|
|||
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:
|
||||
|
@ -264,7 +245,6 @@ def run_startup_files():
|
|||
info("Running /etc/rc.local...")
|
||||
run_command_killable_and_import_envvars("/etc/rc.local")
|
||||
|
||||
|
||||
def run_pre_shutdown_scripts():
|
||||
debug("Running pre-shutdown scripts...")
|
||||
|
||||
|
@ -275,7 +255,6 @@ def run_pre_shutdown_scripts():
|
|||
info("Running %s..." % filename)
|
||||
run_command_killable(filename)
|
||||
|
||||
|
||||
def run_post_shutdown_scripts():
|
||||
debug("Running post-shutdown scripts...")
|
||||
|
||||
|
@ -286,31 +265,26 @@ def run_post_shutdown_scripts():
|
|||
info("Running %s..." % filename)
|
||||
run_command_killable(filename)
|
||||
|
||||
|
||||
def start_runit():
|
||||
def start_runit(runit_services_dir):
|
||||
info("Booting runit daemon...")
|
||||
pid = os.spawnl(os.P_NOWAIT, "/usr/bin/runsvdir", "/usr/bin/runsvdir",
|
||||
"-P", "/etc/service")
|
||||
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(quiet=False):
|
||||
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 /etc/service/* > /dev/null" % KILL_PROCESS_TIMEOUT)
|
||||
os.system("/usr/bin/sv -w %d force-stop %s/* > /dev/null" % (KILL_PROCESS_TIMEOUT, runit_services_dir))
|
||||
|
||||
|
||||
def wait_for_runit_services():
|
||||
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 /etc/service/* | grep -q '^run:'") != 0
|
||||
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
|
||||
|
@ -318,32 +292,28 @@ def wait_for_runit_services():
|
|||
# not to shutdown services that are already being started.
|
||||
# So during shutdown we repeatedly instruct Runit to shutdown
|
||||
# services.
|
||||
shutdown_runit_services(True)
|
||||
|
||||
|
||||
def install_insecure_key():
|
||||
info("Installing insecure SSH key for user root")
|
||||
run_command_killable("/usr/sbin/enable_insecure_key")
|
||||
|
||||
shutdown_runit_services(runit_services_dir, True)
|
||||
|
||||
def main(args):
|
||||
import_envvars(False, False)
|
||||
export_envvars()
|
||||
|
||||
if args.enable_insecure_key:
|
||||
install_insecure_key()
|
||||
|
||||
if not args.skip_startup_files:
|
||||
run_startup_files()
|
||||
|
||||
runit_exited = False
|
||||
exit_code = None
|
||||
|
||||
|
||||
if not args.skip_runit:
|
||||
runit_pid = start_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:
|
||||
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:
|
||||
|
@ -353,52 +323,63 @@ def main(args):
|
|||
exit_status = os.WEXITSTATUS(exit_code)
|
||||
info("Runit exited with status %d" % exit_status)
|
||||
else:
|
||||
info("Running %s..." % " ".join(args.main_command))
|
||||
pid = os.spawnvp(os.P_NOWAIT, args.main_command[0], args.main_command)
|
||||
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." % args.main_command[0])
|
||||
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." % (args.main_command[0], exit_status))
|
||||
info("%s exited with status %d." % (main_command[0], exit_status))
|
||||
except KeyboardInterrupt:
|
||||
stop_child_process(args.main_command[0], pid)
|
||||
stop_child_process(main_command[0], pid)
|
||||
raise
|
||||
except BaseException:
|
||||
warn("An error occurred. Aborting.")
|
||||
stop_child_process(args.main_command[0], pid)
|
||||
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()
|
||||
shutdown_runit_services(runit_services_dir)
|
||||
|
||||
if not runit_exited:
|
||||
stop_child_process("runit daemon", runit_pid)
|
||||
wait_for_runit_services()
|
||||
|
||||
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('--enable-insecure-key', dest='enable_insecure_key',
|
||||
|
||||
parser.add_argument('--no-main-command', dest='no_main_command',
|
||||
action='store_const', const=True, default=False,
|
||||
help='Install the insecure SSH key')
|
||||
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
|
||||
|
||||
|
@ -410,6 +391,7 @@ if args.skip_runit and len(args.main_command) == 0:
|
|||
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:
|
||||
|
@ -417,4 +399,4 @@ except KeyboardInterrupt:
|
|||
exit(2)
|
||||
finally:
|
||||
if args.kill_all_on_exit:
|
||||
kill_all_processes(KILL_ALL_PROCESSES_TIMEOUT)
|
||||
kill_all_processes(KILL_ALL_PROCESSES_TIMEOUT)
|
|
@ -0,0 +1,11 @@
|
|||
[mysqld]
|
||||
character-set-server=utf8mb4
|
||||
|
||||
slow_query_log = {{ default .Env.MYSQL_SLOW_QUERY_LOG "0" }}
|
||||
slow_query_log_file = /var/log/mysql/slow.log
|
||||
long_query_time = 0.2
|
||||
|
||||
max_connections = {{ default .Env.MYSQL_MAX_CONNECTIONS "100" }}
|
||||
|
||||
[client]
|
||||
default-character-set=utf8mb4
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
MYSQL_USER="${MYSQL_USER:-azuracast}"
|
||||
MYSQL_PASSWORD="${MYSQL_PASSWORD:-azur4c457}"
|
||||
MYSQL_DATABASE="${MYSQL_DATABASE:-azuracast}"
|
||||
|
||||
exec gosu mysql mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} -D ${MYSQL_DATABASE}
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
MYSQL_USER="${MYSQL_USER:-azuracast}"
|
||||
MYSQL_PASSWORD="${MYSQL_PASSWORD:-azur4c457}"
|
||||
MYSQL_DATABASE="${MYSQL_DATABASE:-azuracast}"
|
||||
|
||||
cat $1 | mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} -D ${MYSQL_DATABASE}
|
|
@ -0,0 +1,124 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
echo "Switching to dedicated user 'mysql'"
|
||||
exec gosu mysql "$BASH_SOURCE" "$@"
|
||||
fi
|
||||
|
||||
# usage: file_env VAR [DEFAULT]
|
||||
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
|
||||
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
|
||||
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
|
||||
file_env() {
|
||||
local var="$1"
|
||||
local fileVar="${var}_FILE"
|
||||
local def="${2:-}"
|
||||
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
|
||||
mysql_error "Both $var and $fileVar are set (but are exclusive)"
|
||||
fi
|
||||
local val="$def"
|
||||
if [ "${!var:-}" ]; then
|
||||
val="${!var}"
|
||||
elif [ "${!fileVar:-}" ]; then
|
||||
val="$(< "${!fileVar}")"
|
||||
fi
|
||||
export "$var"="$val"
|
||||
unset "$fileVar"
|
||||
}
|
||||
|
||||
# set MARIADB_xyz from MYSQL_xyz when MARIADB_xyz is unset
|
||||
# and make them the same value (so user scripts can use either)
|
||||
_mariadb_file_env() {
|
||||
local var="$1"; shift
|
||||
local maria="MARIADB_${var#MYSQL_}"
|
||||
file_env "$var" "$@"
|
||||
file_env "$maria" "${!var}"
|
||||
if [ "${!maria:-}" ]; then
|
||||
export "$var"="${!maria}"
|
||||
fi
|
||||
}
|
||||
|
||||
# SQL escape the string $1 to be placed in a string literal.
|
||||
# escape, \ followed by '
|
||||
docker_sql_escape_string_literal() {
|
||||
local newline=$'\n'
|
||||
local escaped=${1//\\/\\\\}
|
||||
escaped="${escaped//$newline/\\n}"
|
||||
echo "${escaped//\'/\\\'}"
|
||||
}
|
||||
|
||||
mysql_get_config() {
|
||||
local conf="$1"; shift
|
||||
mysqld --verbose --help 2>/dev/null \
|
||||
| awk -v conf="$conf" '$1 == conf && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
|
||||
}
|
||||
|
||||
# Build env vars
|
||||
DATADIR="$(mysql_get_config 'datadir')"
|
||||
SOCKET="$(mysql_get_config 'socket')"
|
||||
|
||||
_mariadb_file_env 'MYSQL_ROOT_HOST' '%'
|
||||
_mariadb_file_env 'MYSQL_ROOT_PASSWORD'
|
||||
|
||||
: "${MARIADB_ALLOW_EMPTY_ROOT_PASSWORD:=${MYSQL_ALLOW_EMPTY_PASSWORD:-}}"
|
||||
export MYSQL_ALLOW_EMPTY_PASSWORD="$MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" MARIADB_ALLOW_EMPTY_ROOT_PASSWORD
|
||||
: "${MARIADB_RANDOM_ROOT_PASSWORD:=${MYSQL_RANDOM_ROOT_PASSWORD:-}}"
|
||||
export MYSQL_RANDOM_ROOT_PASSWORD="$MARIADB_RANDOM_ROOT_PASSWORD" MARIADB_RANDOM_ROOT_PASSWORD
|
||||
: "${MARIADB_INITDB_SKIP_TZINFO:=${MYSQL_INITDB_SKIP_TZINFO:-}}"
|
||||
export MYSQL_INITDB_SKIP_TZINFO="$MARIADB_INITDB_SKIP_TZINFO" MARIADB_INITDB_SKIP_TZINFO
|
||||
|
||||
if [ -z "$MARIADB_ROOT_PASSWORD" -a -z "$MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" -a -z "$MARIADB_RANDOM_ROOT_PASSWORD" ]; then
|
||||
mysql_error $'Database is uninitialized and password option is not specified\n\tYou need to specify one of MARIADB_ROOT_PASSWORD, MARIADB_ALLOW_EMPTY_ROOT_PASSWORD and MARIADB_RANDOM_ROOT_PASSWORD'
|
||||
fi
|
||||
|
||||
# Spin up temp server
|
||||
echo "Starting temporary MariaDB server..."
|
||||
|
||||
mysqld --skip-networking --skip-grant-tables --socket="${SOCKET}" &
|
||||
|
||||
echo "Waiting for server startup"
|
||||
for i in {30..0}; do
|
||||
if mysql --protocol=socket -hlocalhost -uroot --socket="${SOCKET}" --database=mysql <<<'SELECT 1'; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
if [ "$i" = 0 ]; then
|
||||
echo "Unable to start temporary server."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Try password reset
|
||||
echo "Resetting root password..."
|
||||
|
||||
if [ -n "$MARIADB_RANDOM_ROOT_PASSWORD" ]; then
|
||||
MARIADB_ROOT_PASSWORD="$(pwgen --numerals --capitalize --symbols --remove-chars="'\\" -1 32)"
|
||||
export MARIADB_ROOT_PASSWORD MYSQL_ROOT_PASSWORD=$MARIADB_ROOT_PASSWORD
|
||||
echo "GENERATED ROOT PASSWORD: $MARIADB_ROOT_PASSWORD"
|
||||
fi
|
||||
|
||||
# Sets root password and creates root users for non-localhost hosts
|
||||
rootCreate=
|
||||
rootPasswordEscaped=$( docker_sql_escape_string_literal "${MARIADB_ROOT_PASSWORD}" )
|
||||
|
||||
# default root to listen for connections from anywhere
|
||||
if [ -n "$MARIADB_ROOT_HOST" ] && [ "$MARIADB_ROOT_HOST" != 'localhost' ]; then
|
||||
# no, we don't care if read finds a terminating character in this heredoc
|
||||
# https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151
|
||||
read -r -d '' rootCreate <<-EOSQL || true
|
||||
ALTER USER 'root'@'${MARIADB_ROOT_HOST}' IDENTIFIED BY '${rootPasswordEscaped}' ;
|
||||
GRANT ALL ON *.* TO 'root'@'${MARIADB_ROOT_HOST}' WITH GRANT OPTION ;
|
||||
EOSQL
|
||||
fi
|
||||
|
||||
# tell docker_process_sql to not use MARIADB_ROOT_PASSWORD since it is just now being set
|
||||
# --binary-mode to save us from the semi-mad users go out of their way to confuse the encoding.
|
||||
mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" --database=mysql --binary-mode <<-EOSQL
|
||||
FLUSH PRIVILEGES ;
|
||||
ALTER USER 'root'@'localhost' IDENTIFIED BY '${rootPasswordEscaped}' ;
|
||||
GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ;
|
||||
|
||||
${rootCreate}
|
||||
EOSQL
|
||||
|
||||
echo "Password reset complete."
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ ${MYSQL_SLOW_QUERY_LOG} != 1 ]; then
|
||||
echo "MariaDB Slow Query Log is not currently enabled on this instance."
|
||||
echo "Set MYSQL_SLOW_QUERY_LOG=1 in your environment variables (azuracast.env), then restart to enable."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec gosu mysql mysqldumpslow /var/log/mysql/slow.log
|
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
echo "Switching to dedicated user 'mysql'"
|
||||
exec gosu mysql "$BASH_SOURCE" "$@"
|
||||
fi
|
||||
|
||||
mysql_get_config() {
|
||||
local conf="$1"; shift
|
||||
mysqld --verbose --help 2>/dev/null \
|
||||
| awk -v conf="$conf" '$1 == conf && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
|
||||
}
|
||||
|
||||
DATADIR="$(mysql_get_config 'datadir')"
|
||||
SOCKET="$(mysql_get_config 'socket')"
|
||||
|
||||
echo "Starting temporary MariaDB server..."
|
||||
|
||||
mysqld --skip-networking --skip-grant-tables --socket="${SOCKET}" &
|
||||
|
||||
echo "Waiting for server startup"
|
||||
for i in {30..0}; do
|
||||
if mysql --protocol=socket -hlocalhost -uroot --socket="${SOCKET}" --database=mysql <<<'SELECT 1'; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
if [ "$i" = 0 ]; then
|
||||
echo "Unable to start temporary server."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Upgrading instance (if necessary)..."
|
||||
|
||||
mariadb-upgrade --verbose --protocol=socket -hlocalhost -uroot --socket="${SOCKET}"
|
||||
|
||||
echo "Upgrade complete; Shutting down temporary MariaDB server..."
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec mysqladmin ping -h localhost
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
dockerize -template /etc/mysql/db.cnf.tmpl:/etc/mysql/conf.d/db.cnf
|
||||
|
||||
exec gosu mysql mysqld
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
apt-get update
|
||||
|
||||
# Install common scripts
|
||||
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.full/. /etc/service.full/
|
||||
|
||||
# Run service setup for all setup scripts
|
||||
for f in /bd_build/mariadb/setup/*.sh; do
|
||||
bash "$f" -H
|
||||
done
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
$minimal_apt_get_install tzdata
|
||||
|
||||
echo "1" >> /etc/container_environment/MARIADB_AUTO_UPGRADE
|
||||
|
||||
cp /bd_build/mariadb/mariadb/db.sql /docker-entrypoint-initdb.d/00-azuracast.sql
|
||||
cp /bd_build/mariadb/mariadb/db.cnf.tmpl /etc/mysql/db.cnf.tmpl
|
||||
|
||||
mv /usr/local/bin/healthcheck.sh /usr/local/bin/db_healthcheck.sh
|
||||
mv /usr/local/bin/docker-entrypoint.sh /usr/local/bin/db_entrypoint.sh
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
# If the MariaDB host is anything but localhost, disable MariaDB on this container.
|
||||
if [ "$MYSQL_HOST" != "localhost" ]; then
|
||||
echo "MariaDB host is not localhost; disabling MariaDB..."
|
||||
|
||||
rm -rf /etc/service/mariadb
|
||||
rm -rf /etc/service.minimal/mariadb
|
||||
fi
|
|
@ -0,0 +1,52 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ ! -f /etc/service/mariadb/run ]; then
|
||||
echo "MariaDB disabled. Skipping DB initialization..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
source /usr/local/bin/db_entrypoint.sh
|
||||
|
||||
set -- mysqld
|
||||
|
||||
mysql_note "Initial DB setup..."
|
||||
|
||||
mysql_check_config "$@"
|
||||
# Load various environment variables
|
||||
docker_setup_env "$@"
|
||||
docker_create_db_directories
|
||||
|
||||
# If container is started as root user, restart as dedicated mysql user
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
mysql_note "Switching to dedicated user 'mysql'"
|
||||
exec gosu mysql "${BASH_SOURCE[0]}" "$@"
|
||||
fi
|
||||
|
||||
# there's no database, so it needs to be initialized
|
||||
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
|
||||
docker_verify_minimum_env
|
||||
|
||||
# check dir permissions to reduce likelihood of half-initialized database
|
||||
ls /docker-entrypoint-initdb.d/ > /dev/null
|
||||
|
||||
docker_init_database_dir "$@"
|
||||
|
||||
mysql_note "Starting temporary server"
|
||||
docker_temp_server_start "$@"
|
||||
mysql_note "Temporary server started."
|
||||
|
||||
docker_setup_db
|
||||
docker_process_init_files /docker-entrypoint-initdb.d/*
|
||||
|
||||
mysql_note "Stopping temporary server"
|
||||
docker_temp_server_stop
|
||||
mysql_note "Temporary server stopped"
|
||||
|
||||
echo
|
||||
mysql_note "MariaDB init process done. Ready for start up."
|
||||
echo
|
||||
# MDEV-27636 mariadb_upgrade --check-if-upgrade-is-needed cannot be run offline
|
||||
#elif mysql_upgrade --check-if-upgrade-is-needed; then
|
||||
elif _check_if_upgrade_is_needed; then
|
||||
docker_mariadb_upgrade "$@"
|
||||
fi
|
|
@ -0,0 +1,6 @@
|
|||
save ""
|
||||
|
||||
appendonly no
|
||||
|
||||
maxmemory 128mb
|
||||
maxmemory-policy volatile-lfu
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec gosu redis redis-server /etc/redis/redis.conf
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
apt-get update
|
||||
|
||||
# Install common scripts
|
||||
# cp -rT /bd_build/redis/scripts/ /usr/local/bin
|
||||
|
||||
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.full/. /etc/service.full/
|
||||
|
||||
# Run service setup for all setup scripts
|
||||
for f in /bd_build/redis/setup/*.sh; do
|
||||
bash "$f" -H
|
||||
done
|
|
@ -0,0 +1,12 @@
|
|||
#!/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
|
||||
|
||||
cp /bd_build/redis/redis/redis.conf /etc/redis/redis.conf
|
||||
chown redis:redis /etc/redis/redis.conf
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
|
||||
bool() {
|
||||
case "$1" in
|
||||
Y* | y* | true | TRUE | 1) return 0 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
# If Redis is expressly disabled or the host is anything but localhost, disable Redis on this container.
|
||||
ENABLE_REDIS=${ENABLE_REDIS:-false}
|
||||
|
||||
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
|
||||
fi
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
set -x
|
||||
|
||||
opam init --disable-sandboxing -a --bare && opam switch create 4.13.1
|
||||
|
||||
# Pin specific commit of Liquidsoap
|
||||
opam pin add --no-action liquidsoap https://github.com/savonet/liquidsoap.git#af311dc8ee57e3e7d3f637ea23af4096fd57820d
|
||||
|
||||
opam install -y ladspa.0.2.2 ffmpeg.1.1.1 ffmpeg-avutil.1.1.1 ffmpeg-avcodec.1.1.1 ffmpeg-avdevice.1.1.1 \
|
||||
ffmpeg-av.1.1.1 ffmpeg-avfilter.1.1.1 ffmpeg-swresample.1.1.1 ffmpeg-swscale.1.1.1 frei0r.0.1.2 \
|
||||
samplerate.0.1.6 taglib.0.3.9 mad.0.5.2 faad.0.5.0 fdkaac.0.3.2 lame.0.3.5 vorbis.0.8.0 cry.0.6.6 \
|
||||
flac.0.3.0 opus.0.2.1 dtools.0.4.4 duppy.0.9.2 ocurl.0.9.2 ssl.0.5.10 \
|
||||
liquidsoap
|
||||
|
||||
# Have Liquidsoap build its own chroot.
|
||||
mkdir -p /tmp/liquidsoap
|
||||
|
||||
/var/azuracast/.opam/4.13.1/bin/liquidsoap /bd_build/liquidsoap/build_chroot.liq || true
|
||||
|
||||
# Clear entire OPAM directory
|
||||
rm -rf /var/azuracast/.opam
|
||||
|
||||
cp -r /tmp/liquidsoap/var/azuracast/.opam /var/azuracast/.opam
|
||||
rm -rf /tmp/liquidsoap
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
liquidsoap.chroot.make('/tmp/liquidsoap')
|
||||
shutdown()
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
apt-get update
|
||||
|
||||
# Install common scripts
|
||||
# cp -rT /bd_build/stations/scripts/ /usr/local/bin
|
||||
|
||||
# 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.full/. /etc/service.full/
|
||||
|
||||
# Run service setup for all setup scripts
|
||||
for f in /bd_build/stations/setup/*.sh; do
|
||||
bash "$f" -H
|
||||
done
|
|
@ -0,0 +1,10 @@
|
|||
#!/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
|
||||
|
||||
# SSL self-signed cert generation
|
||||
$minimal_apt_get_install openssl
|
|
@ -0,0 +1,40 @@
|
|||
#!/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 \
|
||||
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 \
|
||||
libsrt-dev libswresample-dev libswscale-dev libtag1-dev libtheora-dev libtiff-dev libx11-dev libxpm-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
|
||||
|
||||
# Per-architecture LS installs
|
||||
ARCHITECTURE=amd64
|
||||
|
||||
if [ "$(uname -m)" = "aarch64" ]; then
|
||||
ARCHITECTURE=arm64
|
||||
fi
|
||||
|
||||
# Adding this comment to trigger an uncached re-pull of this deb file.
|
||||
|
||||
wget -O /tmp/liquidsoap.deb "https://github.com/savonet/liquidsoap/releases/download/v2.0.3/liquidsoap_2.0.3-ubuntu-focal-2_${ARCHITECTURE}.deb"
|
||||
|
||||
dpkg -i /tmp/liquidsoap.deb
|
||||
apt-get install -y -f --no-install-recommends
|
||||
rm -f /tmp/liquidsoap.deb
|
||||
ln -s /usr/bin/liquidsoap /usr/local/bin/liquidsoap
|
||||
|
||||
# To do a pinned install, uncomment and customize below
|
||||
# else
|
||||
# $minimal_apt_get_install build-essential libssl-dev libcurl4-openssl-dev m4 ocaml opam autoconf automake
|
||||
#
|
||||
# sudo -u azuracast bash ../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
|
||||
# apt-get purge -y build-essential libssl-dev libcurl4-openssl-dev m4 ocaml opam autoconf automake
|
||||
# fi
|
|
@ -0,0 +1,12 @@
|
|||
#!/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
|
|
@ -0,0 +1,25 @@
|
|||
[unix_http_server]
|
||||
file=/tmp/supervisor.sock ; (the path to the socket file)
|
||||
|
||||
[inet_http_server] ; inet (TCP) server disabled by default
|
||||
port=127.0.0.1:9001 ; (ip_address:port specifier, *:port for all iface)
|
||||
|
||||
[supervisord]
|
||||
user=root
|
||||
logfile=/var/azuracast/www_tmp/supervisord.log ; (main log file;default $CWD/supervisord.log)
|
||||
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)
|
||||
|
||||
[rpcinterface:supervisor]
|
||||
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/*
|
|
@ -1,11 +1,9 @@
|
|||
{{if isTrue .Env.ENABLE_REDIS }}
|
||||
upstream redis_server {
|
||||
nchan_redis_server "redis://redis:6379";
|
||||
nchan_redis_server "redis://localhost:6379";
|
||||
}
|
||||
{{end}}
|
||||
|
||||
resolver 127.0.0.11;
|
||||
|
||||
server {
|
||||
listen 9010;
|
||||
|
||||
|
@ -130,7 +128,7 @@ server {
|
|||
proxy_connect_timeout 60;
|
||||
|
||||
proxy_set_header Host localhost:$1;
|
||||
proxy_pass http://stations:$1/$3?$args;
|
||||
proxy_pass http://127.0.0.1:$1/$3?$args;
|
||||
}
|
||||
|
||||
# Reverse proxy the Liquidsoap harbor inputs to allow for streaming.
|
||||
|
@ -140,11 +138,9 @@ server {
|
|||
location ~ ^/radio/{{ .Env.NGINX_WEBDJ_PORTS }}(/?)(.*)$ {
|
||||
{{ end }}
|
||||
|
||||
resolver 127.0.0.11;
|
||||
|
||||
include proxy_params;
|
||||
|
||||
proxy_pass http://stations:$1/$3;
|
||||
proxy_pass http://127.0.0.1:$1/$3;
|
||||
}
|
||||
|
||||
# pub/sub endpoints
|
||||
|
|
|
@ -15,6 +15,7 @@ pm.start_servers = 2
|
|||
pm.min_spare_servers = 1
|
||||
pm.max_spare_servers = 3
|
||||
pm.max_requests = 100
|
||||
pm.status_path = /status
|
||||
pm.process_idle_timeout = 60s
|
||||
|
||||
chdir = /
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo 'Spinning up Beanstalkd process...'
|
||||
|
||||
exec sudo -E -u azuracast beanstalkd -p 11300 -z 262140
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
source /etc/php/.version
|
||||
|
||||
exec /usr/sbin/php-fpm${PHP_VERSION} -F --fpm-config /etc/php/${PHP_VERSION}/fpm/php-fpm.conf -c /etc/php/${PHP_VERSION}/fpm/
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec sudo -E -u azuracast php /var/azuracast/www/bin/console azuracast:sync:nowplaying
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec sudo -E -u azuracast php /var/azuracast/www/bin/console queue:process --worker-name=app_worker_0
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [ $(whoami) != 'azuracast' ]; then
|
||||
echo 'This script must be run as the "azuracast" user. Rerunning...'
|
||||
exec gosu azuracast azuracast_ci "$@"
|
||||
fi
|
||||
|
||||
azuracast_install || exit 1
|
||||
|
||||
cd /var/azuracast/www
|
||||
composer codeception-no-coverage
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
if [ `whoami` != 'azuracast' ]; then
|
||||
echo 'This script must be run as the "azuracast" user. Rerunning...'
|
||||
exec sudo -E -u azuracast azuracast_cli "$@"
|
||||
exec gosu azuracast azuracast_cli "$@"
|
||||
fi
|
||||
|
||||
cd /var/azuracast/www
|
||||
|
|
|
@ -9,7 +9,7 @@ bool() {
|
|||
|
||||
if [ $(whoami) != 'azuracast' ]; then
|
||||
echo 'This script must be run as the "azuracast" user. Rerunning...'
|
||||
exec sudo -E -u azuracast azuracast_install "$@"
|
||||
exec gosu azuracast azuracast_install "$@"
|
||||
fi
|
||||
|
||||
echo "AzuraCast Setup"
|
||||
|
|
|
@ -9,7 +9,7 @@ bool() {
|
|||
|
||||
if [ $(whoami) != 'azuracast' ]; then
|
||||
echo 'This script must be run as the "azuracast" user. Rerunning...'
|
||||
exec sudo -E -u azuracast azuracast_restore "$@"
|
||||
exec gosu azuracast azuracast_restore "$@"
|
||||
fi
|
||||
|
||||
echo "AzuraCast Backup Restore"
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
source /etc/container_environment.sh
|
||||
|
||||
exec sudo -E -u azuracast "$@" >/proc/1/fd/1 2>/proc/1/fd/2
|
||||
exec gosu azuracast "$@" >/proc/1/fd/1 2>/proc/1/fd/2
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
exec /usr/sbin/tmpreaper 12h --protect '.tmpreaper' --verbose \
|
||||
/tmp \
|
||||
/tmp/app_nginx_client \
|
||||
/tmp/app_fastcgi_temp \
|
||||
/var/azuracast/stations/*/temp \
|
||||
> /proc/1/fd/1 2> /proc/1/fd/2
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [[ -f /var/azuracast/www/bin/uptime_wait ]]; then
|
||||
if ! php /var/azuracast/www/bin/uptime_wait; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
gosu azuracast php /var/azuracast/www/bin/uptime_wait || exit 1
|
||||
|
||||
exec "$@"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#!/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
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo 'Spinning up Beanstalkd process...'
|
||||
|
||||
exec gosu azuracast beanstalkd -p 11300 -z 262140
|
|
@ -1,8 +1,10 @@
|
|||
#!/bin/sh
|
||||
|
||||
sv -w 30 check php-fpm || exit 1
|
||||
|
||||
# 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
|
||||
exec /usr/sbin/cron -f
|
|
@ -1,5 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
sv -w 30 check php-fpm || exit 1
|
||||
|
||||
bool() {
|
||||
case "$1" in
|
||||
Y* | y* | true | TRUE | 1) return 0 ;;
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
exec php-fpm-healthcheck
|
|
@ -0,0 +1,25 @@
|
|||
#!/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
|
||||
|
||||
# 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" \
|
||||
-template "/etc/php/${PHP_VERSION}/fpm/www.conf.tmpl:/etc/php/${PHP_VERSION}/fpm/pool.d/www.conf" \
|
||||
cp /etc/php/${PHP_VERSION}/fpm/conf.d/05-azuracast.ini /etc/php/${PHP_VERSION}/cli/conf.d/05-azuracast.ini
|
||||
|
||||
# Wait for services to spin up.
|
||||
gosu azuracast php /var/azuracast/www/bin/uptime_wait || exit 1
|
||||
|
||||
# Initialize before running FPM
|
||||
gosu azuracast azuracast_cli azuracast:setup:initialize || exit 1
|
||||
|
||||
# Run PHP-FPM
|
||||
exec /usr/sbin/php-fpm${PHP_VERSION} -F --fpm-config /etc/php/${PHP_VERSION}/fpm/php-fpm.conf -c /etc/php/${PHP_VERSION}/fpm/
|
|
@ -0,0 +1,5 @@
|
|||
#!/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,5 @@
|
|||
#!/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
|
|
@ -3,24 +3,18 @@ set -e
|
|||
source /bd_build/buildconfig
|
||||
set -x
|
||||
|
||||
apt-get update
|
||||
|
||||
# Install common scripts
|
||||
cp -rT /bd_build/scripts/ /usr/local/bin
|
||||
chmod -R a+x /usr/local/bin
|
||||
cp -rT /bd_build/web/scripts/ /usr/local/bin
|
||||
|
||||
# Install runit
|
||||
$minimal_apt_get_install runit
|
||||
cp -rT /bd_build/web/startup_scripts/. /etc/my_init.d/
|
||||
|
||||
# Install runit scripts
|
||||
cp -rT /bd_build/startup_scripts/. /etc/my_init.d/
|
||||
cp -rT /bd_build/runit/. /etc/service/
|
||||
# cp -rT /bd_build/web/service.minimal/. /etc/service.minimal/
|
||||
|
||||
chmod -R +x /etc/service
|
||||
chmod -R +x /etc/my_init.d
|
||||
|
||||
# Install scripts commonly used during setup.
|
||||
$minimal_apt_get_install curl wget tar zip unzip git rsync tzdata gpg-agent openssh-client
|
||||
cp -rT /bd_build/web/service.full/. /etc/service.full/
|
||||
|
||||
# Run service setup for all setup scripts
|
||||
for f in /bd_build/setup/*.sh; do
|
||||
for f in /bd_build/web/setup/*.sh; do
|
||||
bash "$f" -H
|
||||
done
|
||||
done
|
||||
|
|
|
@ -18,5 +18,5 @@ rm -f /etc/cron.daily/dpkg
|
|||
rm -f /etc/cron.daily/password
|
||||
rm -f /etc/cron.weekly/fstrim
|
||||
|
||||
cp -r /bd_build/cron/. /etc/cron.d/
|
||||
cp -r /bd_build/web/cron/. /etc/cron.d/
|
||||
chmod -R 600 /etc/cron.d/*
|
||||
|
|
|
@ -6,9 +6,9 @@ set -x
|
|||
$minimal_apt_get_install nginx nginx-common nginx-extras openssl
|
||||
|
||||
# Install nginx and configuration
|
||||
cp /bd_build/nginx/proxy_params.conf /etc/nginx/proxy_params
|
||||
cp /bd_build/nginx/nginx.conf.tmpl /etc/nginx/nginx.conf.tmpl
|
||||
cp /bd_build/nginx/azuracast.conf.tmpl /etc/nginx/azuracast.conf.tmpl
|
||||
cp /bd_build/web/nginx/proxy_params.conf /etc/nginx/proxy_params
|
||||
cp /bd_build/web/nginx/nginx.conf.tmpl /etc/nginx/nginx.conf.tmpl
|
||||
cp /bd_build/web/nginx/azuracast.conf.tmpl /etc/nginx/azuracast.conf.tmpl
|
||||
|
||||
mkdir -p /etc/nginx/azuracast.conf.d/
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ set -x
|
|||
|
||||
PHP_VERSION=8.1
|
||||
|
||||
echo "${PHP_VERSION}" >> /etc/container_environment/PHP_VERSION
|
||||
|
||||
add-apt-repository -y ppa:ondrej/php
|
||||
apt-get update
|
||||
|
||||
|
@ -18,14 +20,19 @@ $minimal_apt_get_install php${PHP_VERSION}-fpm php${PHP_VERSION}-cli php${PHP_VE
|
|||
mkdir -p /run/php
|
||||
touch /run/php/php${PHP_VERSION}-fpm.pid
|
||||
|
||||
echo "PHP_VERSION=${PHP_VERSION}" >>/etc/php/.version
|
||||
|
||||
cp /bd_build/php/php.ini.tmpl /etc/php/${PHP_VERSION}/fpm/05-azuracast.ini.tmpl
|
||||
cp /bd_build/php/www.conf.tmpl /etc/php/${PHP_VERSION}/fpm/www.conf.tmpl
|
||||
cp /bd_build/web/php/php.ini.tmpl /etc/php/${PHP_VERSION}/fpm/05-azuracast.ini.tmpl
|
||||
cp /bd_build/web/php/www.conf.tmpl /etc/php/${PHP_VERSION}/fpm/www.conf.tmpl
|
||||
|
||||
# Install Composer
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer
|
||||
|
||||
# Download PHP-FPM healthcheck script
|
||||
$minimal_apt_get_install 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
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ $minimal_apt_get_install sftpgo
|
|||
|
||||
mkdir -p /var/azuracast/sftpgo/persist /var/azuracast/sftpgo/backups
|
||||
|
||||
cp /bd_build/sftpgo/sftpgo.json /var/azuracast/sftpgo/sftpgo.json
|
||||
cp /bd_build/web/sftpgo/sftpgo.json /var/azuracast/sftpgo/sftpgo.json
|
||||
|
||||
touch /var/azuracast/sftpgo/sftpgo.db
|
||||
chown -R azuracast:azuracast /var/azuracast/sftpgo
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copy the php.ini template to its destination.
|
||||
source /etc/php/.version
|
||||
|
||||
dockerize -template "/etc/php/${PHP_VERSION}/fpm/05-azuracast.ini.tmpl:/etc/php/${PHP_VERSION}/fpm/conf.d/05-azuracast.ini" \
|
||||
-template "/etc/php/${PHP_VERSION}/fpm/www.conf.tmpl:/etc/php/${PHP_VERSION}/fpm/pool.d/www.conf" \
|
||||
cp /etc/php/${PHP_VERSION}/fpm/conf.d/05-azuracast.ini /etc/php/${PHP_VERSION}/cli/conf.d/05-azuracast.ini
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
exec sudo -E -u azuracast azuracast_cli azuracast:setup:initialize
|
Loading…
Reference in New Issue