diff --git a/.codespellignore b/.codespellignore index dfa876084..d71f78f01 100644 --- a/.codespellignore +++ b/.codespellignore @@ -1,6 +1,7 @@ +conexant hda HDA -conexant +ro # Names flor diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..9cd0ce289 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +*/install/ +*/Makefile +*/README.md +*/tests/ +*/tools/ +.* + +# Specific ignores +api/schema.yml + +# Required files +!legacy/install/php/libretime-legacy.ini +!legacy/Makefile diff --git a/.env.dev b/.env.dev new file mode 100644 index 000000000..a088db825 --- /dev/null +++ b/.env.dev @@ -0,0 +1,3 @@ +LIBRETIME_VERSION=main +LIBRETIME_CONFIG_FILEPATH=./docker/config.dev.yml +NGINX_CONFIG_FILEPATH=./docker/nginx.conf diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..1e3b0833d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,250 @@ +#======================================================================================# +# Python Builder # +#======================================================================================# +FROM python:3.9-bullseye as python-builder + +WORKDIR /build + +# Wheels +WORKDIR /build/shared +COPY shared . +RUN pip wheel --wheel-dir . --no-deps . + +WORKDIR /build/api-client +COPY api-client . +RUN pip wheel --wheel-dir . --no-deps . + +#======================================================================================# +# Python base # +#======================================================================================# +FROM python:3.9-slim-bullseye as python-base + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +# Custom user +ARG USER=libretime +ARG UID=1000 +ARG GID=1000 + +RUN adduser --disabled-password --uid=$UID --gecos '' --no-create-home ${USER} + +RUN install --directory --owner=${USER} \ + /etc/libretime \ + /srv/libretime + +ENV LIBRETIME_CONFIG_FILEPATH=/etc/libretime/config.yml + +# Shared packages +COPY tools/packages.py /tmp/packages.py +COPY shared/packages.ini /tmp/packages.ini + +RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + $(python3 /tmp/packages.py --format=line --exclude=python bullseye /tmp/packages.ini) \ + && rm -rf /var/lib/apt/lists/* \ + && rm -f /tmp/packages.py /tmp/packages.ini + +#======================================================================================# +# Python base with ffmpeg # +#======================================================================================# +FROM python-base as python-base-ffmpeg + +RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + ffmpeg \ + && rm -rf /var/lib/apt/lists/* + +#======================================================================================# +# Analyzer # +#======================================================================================# +FROM python-base-ffmpeg as libretime-analyzer + +COPY tools/packages.py /tmp/packages.py +COPY analyzer/packages.ini /tmp/packages.ini + +RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + $(python3 /tmp/packages.py --format=line --exclude=python bullseye /tmp/packages.ini) \ + && rm -rf /var/lib/apt/lists/* \ + && rm -f /tmp/packages.py /tmp/packages.ini + +WORKDIR /src + +COPY analyzer/requirements.txt . +RUN pip --no-cache-dir install --no-compile -r requirements.txt + +COPY --from=python-builder /build/shared/*.whl . +RUN pip --no-cache-dir install --no-compile *.whl && rm -Rf *.whl + +COPY analyzer . +RUN pip --no-cache-dir install --editable . && rm -Rf /root/.cache + +# Run +USER ${UID}:${GID} +WORKDIR /app + +CMD ["/usr/local/bin/libretime-analyzer"] + +#======================================================================================# +# API # +#======================================================================================# +FROM python-base as libretime-api + +RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + gcc \ + libc6-dev \ + libpq-dev \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /src + +COPY api/requirements.txt . +RUN pip --no-cache-dir install --no-compile gunicorn uvicorn -r requirements.txt + +COPY --from=python-builder /build/shared/*.whl . +RUN pip --no-cache-dir install --no-compile *.whl && rm -Rf *.whl + +COPY api . +RUN pip --no-cache-dir install --editable .[prod] && rm -Rf /root/.cache + +# Run +USER ${UID}:${GID} +WORKDIR /app + +CMD ["/usr/local/bin/gunicorn", \ + "--workers=4", \ + "--worker-class=uvicorn.workers.UvicornWorker", \ + "--log-file", "-", \ + "--bind=0.0.0.0:9001", \ + "libretime_api.asgi"] + +#======================================================================================# +# Playout # +#======================================================================================# +FROM python-base-ffmpeg as libretime-playout + +COPY tools/packages.py /tmp/packages.py +COPY playout/packages.ini /tmp/packages.ini + +RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + $(python3 /tmp/packages.py --format=line --exclude=python bullseye /tmp/packages.ini) \ + && rm -rf /var/lib/apt/lists/* \ + && rm -f /tmp/packages.py /tmp/packages.ini + +WORKDIR /src + +COPY playout/requirements.txt . +RUN pip --no-cache-dir install --no-compile -r requirements.txt + +COPY --from=python-builder /build/shared/*.whl . +COPY --from=python-builder /build/api-client/*.whl . +RUN pip --no-cache-dir install --no-compile *.whl && rm -Rf *.whl + +COPY playout . +RUN pip --no-cache-dir install --editable . && rm -Rf /root/.cache + +# Run +USER ${UID}:${GID} +WORKDIR /app + +CMD ["/usr/local/bin/libretime-playout"] + +#======================================================================================# +# Worker # +#======================================================================================# +FROM python-base as libretime-worker + +WORKDIR /src + +COPY worker/requirements.txt . +RUN pip --no-cache-dir install --no-compile -r requirements.txt + +COPY --from=python-builder /build/shared/*.whl . +RUN pip --no-cache-dir install --no-compile *.whl && rm -Rf *.whl + +COPY worker . +RUN pip --no-cache-dir install --editable . && rm -Rf /root/.cache + +# Run +USER ${UID}:${GID} +WORKDIR /app + +CMD ["/usr/local/bin/celery", "worker", \ + "--app=libretime_worker.tasks:worker", \ + "--config=libretime_worker.config", \ + "--time-limit=1800", \ + "--concurrency=1", \ + "--loglevel=info"] + +#======================================================================================# +# Legacy # +#======================================================================================# +FROM php:7.4-fpm as libretime-legacy + +ENV LIBRETIME_CONFIG_FILEPATH=/etc/libretime/config.yml + +# Custom user +ARG USER=libretime +ARG UID=1000 +ARG GID=1000 + +RUN adduser --disabled-password --uid=$UID --gecos '' --no-create-home ${USER} + +RUN install --directory --owner=${USER} \ + /etc/libretime \ + /srv/libretime + +RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + gettext \ + libcurl4-openssl-dev \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libonig-dev \ + libpng-dev \ + libpq-dev \ + libxml2-dev \ + libyaml-dev \ + libzip-dev \ + locales \ + unzip \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* \ + && pecl install apcu yaml \ + && docker-php-ext-enable apcu yaml \ + && docker-php-ext-configure gd --with-freetype --with-jpeg \ + && docker-php-ext-install -j$(nproc) \ + bcmath \ + curl \ + exif \ + gd \ + gettext \ + mbstring \ + opcache \ + pdo_pgsql \ + pgsql \ + sockets \ + xml + +COPY legacy/locale/locale.gen /etc/locale.gen +RUN locale-gen + +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" +COPY "legacy/install/php/libretime-legacy.ini" "$PHP_INI_DIR/conf.d/" + +COPY --from=composer /usr/bin/composer /usr/local/bin/composer + +WORKDIR /var/www/html + +COPY legacy/composer.* ./ +RUN composer --no-cache install --no-progress --no-interaction --no-dev --no-autoloader + +COPY legacy . +RUN make locale-build +RUN composer --no-cache dump-autoload --no-interaction --no-dev + +# Run +USER ${UID}:${GID} diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 000000000..cfc4dcdbc --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,67 @@ +# +# This file is used for development. It it not intended for production! +# See https://libretime.org/docs/developer-manual/development/environment/#docker-compose +# +version: "3.9" + +services: + postgres: + ports: + - 5432:5432 + + rabbitmq: + image: rabbitmq:management-alpine + ports: + - 5672:5672 + - 15672:15672 + + playout: + build: + context: . + target: libretime-playout + volumes: + - ./playout:/src + + liquidsoap: + build: + context: . + target: libretime-playout + ports: + - 1234:1234 + volumes: + - ./playout:/src + + analyzer: + build: + context: . + target: libretime-analyzer + volumes: + - ./analyzer:/src + + worker: + build: + context: . + target: libretime-worker + volumes: + - ./worker:/src + + api: + build: + context: . + target: libretime-api + volumes: + - ./api:/src + command: /usr/local/bin/libretime-api runserver 0.0.0.0:9001 + environment: + LIBRETIME_DEBUG: "true" + + legacy: + build: + context: . + target: libretime-legacy + volumes: + - ./legacy:/var/www/html + + nginx: + volumes: + - ./legacy:/var/www/html diff --git a/docker-compose.yml b/docker-compose.yml index 333420ff1..87d430c52 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,27 +3,108 @@ version: "3.9" services: postgres: image: postgres - ports: - - 5432:5432 volumes: - postgres_data:/var/lib/postgresql/data environment: POSTGRES_USER: libretime - POSTGRES_PASSWORD: libretime + POSTGRES_PASSWORD: libretime # Change me ! healthcheck: test: pg_isready -U libretime rabbitmq: - image: rabbitmq:management-alpine - ports: - - 5672:5672 - - 15672:15672 + image: rabbitmq:alpine environment: RABBITMQ_DEFAULT_VHOST: /libretime RABBITMQ_DEFAULT_USER: libretime - RABBITMQ_DEFAULT_PASS: libretime + RABBITMQ_DEFAULT_PASS: libretime # Change me ! healthcheck: test: rabbitmq-diagnostics -q ping + playout: + image: ghcr.io/libretime/libretime-playout:${LIBRETIME_VERSION:-latest} + depends_on: + - rabbitmq + volumes: + - ${LIBRETIME_CONFIG_FILEPATH:-./config.yml}:/etc/libretime/config.yml:ro + - libretime_playout:/app + environment: + LIBRETIME_GENERAL_PUBLIC_URL: http://nginx + + liquidsoap: + image: ghcr.io/libretime/libretime-playout:${LIBRETIME_VERSION:-latest} + command: /usr/local/bin/libretime-liquidsoap + ports: + - 8001:8001 + - 8002:8002 + depends_on: + - rabbitmq + volumes: + - ${LIBRETIME_CONFIG_FILEPATH:-./config.yml}:/etc/libretime/config.yml:ro + - libretime_playout:/app + environment: + LIBRETIME_GENERAL_PUBLIC_URL: http://nginx + + analyzer: + image: ghcr.io/libretime/libretime-analyzer:${LIBRETIME_VERSION:-latest} + depends_on: + - rabbitmq + volumes: + - ${LIBRETIME_CONFIG_FILEPATH:-./config.yml}:/etc/libretime/config.yml:ro + - libretime_storage:/srv/libretime + environment: + LIBRETIME_GENERAL_PUBLIC_URL: http://nginx + + worker: + image: ghcr.io/libretime/libretime-worker:${LIBRETIME_VERSION:-latest} + depends_on: + - rabbitmq + volumes: + - ${LIBRETIME_CONFIG_FILEPATH:-./config.yml}:/etc/libretime/config.yml:ro + environment: + LIBRETIME_GENERAL_PUBLIC_URL: http://nginx + + api: + image: ghcr.io/libretime/libretime-api:${LIBRETIME_VERSION:-latest} + depends_on: + - postgres + - rabbitmq + volumes: + - ${LIBRETIME_CONFIG_FILEPATH:-./config.yml}:/etc/libretime/config.yml:ro + - libretime_storage:/srv/libretime + healthcheck: + test: python3 -c "import requests; requests.get('http://localhost:9001/api/v2/version').raise_for_status()" + + legacy: + image: ghcr.io/libretime/libretime-legacy:${LIBRETIME_VERSION:-latest} + depends_on: + - postgres + - rabbitmq + volumes: + - ${LIBRETIME_CONFIG_FILEPATH:-./config.yml}:/etc/libretime/config.yml:ro + - libretime_assets:/var/www/html + - libretime_storage:/srv/libretime + environment: + LIBRETIME_LOG_FILEPATH: php://stderr + + nginx: + image: nginx + ports: + - 8080:80 + volumes: + - libretime_assets:/var/www/html:ro + - ${NGINX_CONFIG_FILEPATH:-./nginx.conf}:/etc/nginx/conf.d/default.conf:ro + + icecast: + image: infiniteproject/icecast + ports: + - 8000:8000 + environment: + ICECAST_SOURCE_PASSWORD: hackme # Change me ! + ICECAST_ADMIN_PASSWORD: hackme # Change me ! + ICECAST_RELAY_PASSWORD: hackme # Change me ! + volumes: postgres_data: {} + libretime_storage: {} + libretime_assets: {} + libretime_playout: {} diff --git a/docker/config.dev.yml b/docker/config.dev.yml new file mode 100644 index 000000000..aa4d3fa02 --- /dev/null +++ b/docker/config.dev.yml @@ -0,0 +1,35 @@ +general: + public_url: http://localhost:8080 + api_key: some_secret_api_key + +database: + host: postgres + +rabbitmq: + host: rabbitmq + +playout: + liquidsoap_host: liquidsoap + +liquidsoap: + server_listen_address: 0.0.0.0 + +stream: + outputs: + .default_icecast_output: &default_icecast_output + host: icecast + port: 8000 + source_password: hackme + admin_password: hackme + name: LibreTime! + description: LibreTime Radio! + website: https://libretime.org + genre: various + + icecast: + - <<: *default_icecast_output + enabled: true + mount: main + audio: + format: ogg + bitrate: 256 diff --git a/docker/config.yml b/docker/config.yml new file mode 100644 index 000000000..ed21a46cb --- /dev/null +++ b/docker/config.yml @@ -0,0 +1,267 @@ +# See https://libretime.org/docs/admin-manual/setup/configuration/ + +general: + # The public url. + # > this field is REQUIRED + public_url: + # The internal API authentication key. + # > this field is REQUIRED + api_key: + + # List of origins allowed to access resources on the server, the public url + # origin is automatically included. + # > default is [] + allowed_cors_origins: [] + + # How many hours ahead Playout should cache scheduled media files. + # > default is 1 + cache_ahead_hours: 1 + + # Authentication adaptor to use for the legacy service, specify a class like + # LibreTime_Auth_Adaptor_FreeIpa to replace the built-in adaptor. + # > default is local + auth: local + +storage: + # Path of the storage directory. + # > default is /srv/libretime + path: /srv/libretime + +database: + # The hostname of the PostgreSQL server. + # > default is localhost + host: postgres + # The port of the PostgreSQL server. + # > default is 5432 + port: 5432 + # The name of the PostgreSQL database. + # > default is libretime + name: libretime + # The username of the PostgreSQL user. + # > default is libretime + user: libretime + # The password of the PostgreSQL user. + # > default is libretime + password: libretime + +rabbitmq: + # The hostname of the RabbitMQ server. + # > default is localhost + host: rabbitmq + # The port of the RabbitMQ server. + # > default is 5672 + port: 5672 + # The virtual host of RabbitMQ server. + # > default is /libretime + vhost: /libretime + # The username of the RabbitMQ user. + # > default is libretime + user: libretime + # The password of the RabbitMQ user. + # > default is libretime + password: libretime + +playout: + # Liquidsoap connection host. + # > default is localhost + liquidsoap_host: liquidsoap + # Liquidsoap connection port. + # > default is 1234 + liquidsoap_port: 1234 + + # The format for recordings. + # > must be one of (ogg, mp3) + # > default is ogg + record_file_format: ogg + # The bitrate for recordings. + # > default is 256 + record_bitrate: 256 + # The samplerate for recordings. + # > default is 44100 + record_samplerate: 44100 + # The number of channels for recordings. + # > default is 2 + record_channels: 2 + # The sample size for recordings. + # > default is 16 + record_sample_size: 16 + +liquidsoap: + # Liquidsoap server listen address. + # > default is 127.0.0.1 + server_listen_address: 0.0.0.0 + # Liquidsoap server listen port. + # > default is 1234 + server_listen_port: 1234 + + # Input harbor listen address. + # > default is ["0.0.0.0"] + harbor_listen_address: ["0.0.0.0"] + +stream: + # Inputs sources. + inputs: + # Main harbor input. + main: + # Harbor input public url. If not defined, the value will be generated from + # the [general.public_url] hostname, the input port and mount. + public_url: + # Mount point for the main harbor input. + # > default is main + mount: main + # Listen port for the main harbor input. + # > default is 8001 + port: 8001 + + # Show harbor input. + show: + # Harbor input public url. If not defined, the value will be generated from + # the [general.public_url] hostname, the input port and mount. + public_url: + # Mount point for the show harbor input. + # > default is show + mount: show + # Listen port for the show harbor input. + # > default is 8002 + port: 8002 + + # Output streams. + outputs: + # Default icecast output + # This can be reused to define multiple outputs without duplicating data + .default_icecast_output: &default_icecast_output + host: icecast + port: 8000 + source_password: hackme + admin_password: hackme + name: LibreTime! + description: LibreTime Radio! + website: https://libretime.org + genre: various + + # Icecast output streams. + # > max items is 3 + icecast: + # The default Icecast output stream + - <<: *default_icecast_output + enabled: true + public_url: + mount: main + audio: + format: ogg + bitrate: 256 + + # You can define extra outputs by reusing the default output using a yaml anchor + - <<: *default_icecast_output + enabled: false + mount: extra + + - # Whether the output is enabled. + # > default is false + enabled: false + # Output public url, If not defined, the value will be generated from + # the [general.public_url] hostname, the output port and mount. + public_url: + # Icecast server host. + # > default is localhost + host: localhost + # Icecast server port. + # > default is 8000 + port: 8000 + # Icecast server mount point. + # > this field is REQUIRED + mount: main + # Icecast source user. + # > default is source + source_user: source + # Icecast source password. + # > this field is REQUIRED + source_password: hackme + # Icecast admin user. + # > default is admin + admin_user: admin + # Icecast admin password. If not defined, statistics will not be collected. + admin_password: hackme + + # Icecast output audio. + audio: + # Icecast output audio format. + # > must be one of (aac, mp3, ogg, opus) + # > this field is REQUIRED + format: ogg + # Icecast output audio bitrate. + # > must be one of (32, 48, 64, 96, 128, 160, 192, 224, 256, 320) + # > this field is REQUIRED + bitrate: 256 + + # format=ogg only field: Embed metadata (track title, artist, and show name) + # in the output stream. Some bugged players will disconnect from the stream + # after every songs when playing ogg streams that have metadata information + # enabled. + # > default is false + enable_metadata: false + + # Icecast stream name. + name: LibreTime! + # Icecast stream description. + description: LibreTime Radio! + # Icecast stream website. + website: https://libretime.org + # Icecast stream genre. + genre: various + + # Shoutcast output streams. + # > max items is 1 + shoutcast: + - # Whether the output is enabled. + # > default is false + enabled: false + # Output public url. If not defined, the value will be generated from + # the [general.public_url] hostname and the output port. + public_url: + # Shoutcast server host. + # > default is localhost + host: localhost + # Shoutcast server port. + # > default is 8000 + port: 8000 + # Shoutcast source user. + # > default is source + source_user: source + # Shoutcast source password. + # > this field is REQUIRED + source_password: hackme + # Shoutcast admin user. + # > default is admin + admin_user: admin + # Shoutcast admin password. If not defined, statistics will not be collected. + admin_password: hackme + + # Shoutcast output audio. + audio: + # Shoutcast output audio format. + # > must be one of (aac, mp3) + # > this field is REQUIRED + format: mp3 + # Shoutcast output audio bitrate. + # > must be one of (32, 48, 64, 96, 128, 160, 192, 224, 256, 320) + # > this field is REQUIRED + bitrate: 256 + + # Shoutcast stream name. + name: LibreTime! + # Shoutcast stream website. + website: https://libretime.org + # Shoutcast stream genre. + genre: various + + # System outputs. + # > max items is 1 + system: + - # Whether the output is enabled. + # > default is false + enabled: false + # System output kind. + # > must be one of (alsa, ao, oss, portaudio, pulseaudio) + # > default is alsa + kind: alsa diff --git a/docker/example/config.yml b/docker/example/config.yml new file mode 100644 index 000000000..fbd3d4e8f --- /dev/null +++ b/docker/example/config.yml @@ -0,0 +1,267 @@ +# See https://libretime.org/docs/admin-manual/setup/configuration/ + +general: + # The public url. + # > this field is REQUIRED + public_url: http://localhost:8080 + # The internal API authentication key. + # > this field is REQUIRED + api_key: some_secret_api_key + + # List of origins allowed to access resources on the server, the public url + # origin is automatically included. + # > default is [] + allowed_cors_origins: [] + + # How many hours ahead Playout should cache scheduled media files. + # > default is 1 + cache_ahead_hours: 1 + + # Authentication adaptor to use for the legacy service, specify a class like + # LibreTime_Auth_Adaptor_FreeIpa to replace the built-in adaptor. + # > default is local + auth: local + +storage: + # Path of the storage directory. + # > default is /srv/libretime + path: /srv/libretime + +database: + # The hostname of the PostgreSQL server. + # > default is localhost + host: postgres + # The port of the PostgreSQL server. + # > default is 5432 + port: 5432 + # The name of the PostgreSQL database. + # > default is libretime + name: libretime + # The username of the PostgreSQL user. + # > default is libretime + user: libretime + # The password of the PostgreSQL user. + # > default is libretime + password: libretime + +rabbitmq: + # The hostname of the RabbitMQ server. + # > default is localhost + host: rabbitmq + # The port of the RabbitMQ server. + # > default is 5672 + port: 5672 + # The virtual host of RabbitMQ server. + # > default is /libretime + vhost: /libretime + # The username of the RabbitMQ user. + # > default is libretime + user: libretime + # The password of the RabbitMQ user. + # > default is libretime + password: libretime + +playout: + # Liquidsoap connection host. + # > default is localhost + liquidsoap_host: liquidsoap + # Liquidsoap connection port. + # > default is 1234 + liquidsoap_port: 1234 + + # The format for recordings. + # > must be one of (ogg, mp3) + # > default is ogg + record_file_format: ogg + # The bitrate for recordings. + # > default is 256 + record_bitrate: 256 + # The samplerate for recordings. + # > default is 44100 + record_samplerate: 44100 + # The number of channels for recordings. + # > default is 2 + record_channels: 2 + # The sample size for recordings. + # > default is 16 + record_sample_size: 16 + +liquidsoap: + # Liquidsoap server listen address. + # > default is 127.0.0.1 + server_listen_address: 0.0.0.0 + # Liquidsoap server listen port. + # > default is 1234 + server_listen_port: 1234 + + # Input harbor listen address. + # > default is ["0.0.0.0"] + harbor_listen_address: ["0.0.0.0"] + +stream: + # Inputs sources. + inputs: + # Main harbor input. + main: + # Harbor input public url. If not defined, the value will be generated from + # the [general.public_url] hostname, the input port and mount. + public_url: + # Mount point for the main harbor input. + # > default is main + mount: main + # Listen port for the main harbor input. + # > default is 8001 + port: 8001 + + # Show harbor input. + show: + # Harbor input public url. If not defined, the value will be generated from + # the [general.public_url] hostname, the input port and mount. + public_url: + # Mount point for the show harbor input. + # > default is show + mount: show + # Listen port for the show harbor input. + # > default is 8002 + port: 8002 + + # Output streams. + outputs: + # Default icecast output + # This can be reused to define multiple outputs without duplicating data + .default_icecast_output: &default_icecast_output + host: icecast + port: 8000 + source_password: hackme + admin_password: hackme + name: LibreTime! + description: LibreTime Radio! + website: https://libretime.org + genre: various + + # Icecast output streams. + # > max items is 3 + icecast: + # The default Icecast output stream + - <<: *default_icecast_output + enabled: true + public_url: + mount: main + audio: + format: ogg + bitrate: 256 + + # You can define extra outputs by reusing the default output using a yaml anchor + - <<: *default_icecast_output + enabled: false + mount: extra + + - # Whether the output is enabled. + # > default is false + enabled: false + # Output public url, If not defined, the value will be generated from + # the [general.public_url] hostname, the output port and mount. + public_url: + # Icecast server host. + # > default is localhost + host: localhost + # Icecast server port. + # > default is 8000 + port: 8000 + # Icecast server mount point. + # > this field is REQUIRED + mount: main + # Icecast source user. + # > default is source + source_user: source + # Icecast source password. + # > this field is REQUIRED + source_password: hackme + # Icecast admin user. + # > default is admin + admin_user: admin + # Icecast admin password. If not defined, statistics will not be collected. + admin_password: hackme + + # Icecast output audio. + audio: + # Icecast output audio format. + # > must be one of (aac, mp3, ogg, opus) + # > this field is REQUIRED + format: ogg + # Icecast output audio bitrate. + # > must be one of (32, 48, 64, 96, 128, 160, 192, 224, 256, 320) + # > this field is REQUIRED + bitrate: 256 + + # format=ogg only field: Embed metadata (track title, artist, and show name) + # in the output stream. Some bugged players will disconnect from the stream + # after every songs when playing ogg streams that have metadata information + # enabled. + # > default is false + enable_metadata: false + + # Icecast stream name. + name: LibreTime! + # Icecast stream description. + description: LibreTime Radio! + # Icecast stream website. + website: https://libretime.org + # Icecast stream genre. + genre: various + + # Shoutcast output streams. + # > max items is 1 + shoutcast: + - # Whether the output is enabled. + # > default is false + enabled: false + # Output public url. If not defined, the value will be generated from + # the [general.public_url] hostname and the output port. + public_url: + # Shoutcast server host. + # > default is localhost + host: localhost + # Shoutcast server port. + # > default is 8000 + port: 8000 + # Shoutcast source user. + # > default is source + source_user: source + # Shoutcast source password. + # > this field is REQUIRED + source_password: hackme + # Shoutcast admin user. + # > default is admin + admin_user: admin + # Shoutcast admin password. If not defined, statistics will not be collected. + admin_password: hackme + + # Shoutcast output audio. + audio: + # Shoutcast output audio format. + # > must be one of (aac, mp3) + # > this field is REQUIRED + format: mp3 + # Shoutcast output audio bitrate. + # > must be one of (32, 48, 64, 96, 128, 160, 192, 224, 256, 320) + # > this field is REQUIRED + bitrate: 256 + + # Shoutcast stream name. + name: LibreTime! + # Shoutcast stream website. + website: https://libretime.org + # Shoutcast stream genre. + genre: various + + # System outputs. + # > max items is 1 + system: + - # Whether the output is enabled. + # > default is false + enabled: false + # System output kind. + # > must be one of (alsa, ao, oss, portaudio, pulseaudio) + # > default is alsa + kind: alsa diff --git a/docker/example/docker-compose.yml b/docker/example/docker-compose.yml new file mode 120000 index 000000000..b3774a09e --- /dev/null +++ b/docker/example/docker-compose.yml @@ -0,0 +1 @@ +../../docker-compose.yml \ No newline at end of file diff --git a/docker/example/nginx.conf b/docker/example/nginx.conf new file mode 120000 index 000000000..d04aa9ccf --- /dev/null +++ b/docker/example/nginx.conf @@ -0,0 +1 @@ +../nginx.conf \ No newline at end of file diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 000000000..46748a871 --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,43 @@ +server { + listen 80; + listen [::]:80; + + root /var/www/html/public; + + index index.php index.html index.htm; + + client_max_body_size 512M; + client_body_timeout 300s; + + location ~ \.php$ { + fastcgi_buffers 64 4K; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + + #try_files $uri =404; + try_files $fastcgi_script_name =404; + + include fastcgi_params; + + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + set $path_info $fastcgi_path_info; + fastcgi_param PATH_INFO $path_info; + include fastcgi_params; + + fastcgi_index index.php; + fastcgi_pass legacy:9000; + } + + location / { + try_files $uri $uri/ /index.php$is_args$args; + } + + location ~ ^/api/(v2|browser) { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + proxy_redirect off; + proxy_pass http://api:9001; + } +} diff --git a/docs/admin-manual/setup/install.md b/docs/admin-manual/setup/install.md index 819572b99..aa28fa6c9 100644 --- a/docs/admin-manual/setup/install.md +++ b/docs/admin-manual/setup/install.md @@ -19,19 +19,15 @@ If you are coming from **Airtime**, please follow the [Airtime migration guide]( You can install LibreTime using the one of the following methods: - [:rocket: Using the installer](#using-the-installer) -- :construction: Using Ansible +- [:rocket: Using docker-compose](#using-docker-compose) +- :construction: Using ansible -#### Minimum system requirements +### Minimum system requirements - 1 Ghz Processor - 2 GB RAM recommended (1 GB required) - A static external IP address ([How to setup a static ip using Netplan](../tutorials/setup-a-static-ip-using-netplan.md)) -One of the [supported distribution releases](../../developer-manual/development/releases.md#distributions-releases-support): - -- [Debian 11](https://www.debian.org/releases/) -- [Ubuntu 20.04 LTS](https://wiki.ubuntu.com/Releases) - :::warning Make sure that you have configured a **firewall** and it's not blocking connection to the desired ports. @@ -50,6 +46,11 @@ LibreTime requires the following default ports to be open: The installer is shipped in the released tarballs or directly in the project repository. +We recommend installing on one of the following [distribution releases](../../developer-manual/development/releases.md#distributions-releases-support): + +- [Debian 11](https://www.debian.org/releases/) +- [Ubuntu 20.04 LTS](https://wiki.ubuntu.com/Releases) + ### Before installing Before installing LibreTime, you need to make sure you operating system is properly configured. @@ -207,13 +208,83 @@ sudo systemctl start libretime.target sudo systemctl --all --plain | grep libretime ``` -#### Configure +Next, continue by [configuring your installation](#configure). + +## Using docker-compose + +:::warning + +The docker-compose install is still a work in progress and is **EXPERIMENTAL**, breaking changes may occur without notice. + +::: + +### Download + +Pick the version you want to install: + + +echo LIBRETIME_VERSION="{vars.version}" > .env + + +Download the docker-compose files from the repository: + +```bash +# Load LIBRETIME_VERSION variable +source .env + +wget "https://raw.githubusercontent.com/libretime/libretime/$LIBRETIME_VERSION/docker-compose.yml" +wget "https://raw.githubusercontent.com/libretime/libretime/$LIBRETIME_VERSION/docker/nginx.conf" +wget "https://raw.githubusercontent.com/libretime/libretime/$LIBRETIME_VERSION/docker/config.yml" +``` + +### Setup + +Once the files are downloaded, edit the [configuration file](./configuration.md) at `./config.yml` to fill required information and to match your needs. + +:::info + +The `docker/config.yml` configuration file you previously downloaded already contains specific values required by the container setup, you should not change them: + +```yaml +database: + host: "postgres" +rabbitmq: + host: "rabbitmq" +playout: + liquidsoap_host: "liquidsoap" +liquidsoap: + server_listen_address: "0.0.0.0" +stream: + outputs: + .default_icecast_output: + host: "icecast" +``` + +::: + +Next, run the following commands to setup the database: + +```bash +docker-compose run --rm api libretime-api migrate +``` + +Finally, start the services, and check that they are running properly using the following commands: + +```bash +docker-compose up -d + +docker-compose logs -f +``` + +Next, continue by [configuring your installation](#configure). + +## Configure Once the setup is completed, log in the interface and make sure to edit the project settings (go to **Settings** > **General**) to match your needs. Important settings are: - Timezone - First day of the week -### Next +## Next Once completed, it's recommended to [install a reverse proxy](./reverse-proxy.md) to setup SSL termination and secure your installation. diff --git a/docs/developer-manual/development/environment.md b/docs/developer-manual/development/environment.md index c55b07ab4..a2943a065 100644 --- a/docs/developer-manual/development/environment.md +++ b/docs/developer-manual/development/environment.md @@ -2,6 +2,25 @@ title: Development environment --- +## Docker-compose + +To setup a docker-compose development environment, run the following commands: + +```bash +# Clean and build +make clean +cp .env.dev .env +docker-compose build + +# Setup +docker-compose run --rm legacy make build +docker-compose run --rm api libretime-api migrate + +# Run +docker-compose up -d +docker-compose logs -f +``` + ## Vagrant To use Vagrant, you need to install a virtualization engine: [VirtualBox](https://www.virtualbox.org) or Libvirt. The [vagrant-vbguest] package on Github can help maintain guest extensions on host systems using VirtualBox. diff --git a/legacy/install/php/libretime-legacy.ini b/legacy/install/php/libretime-legacy.ini new file mode 100644 index 000000000..77171108e --- /dev/null +++ b/legacy/install/php/libretime-legacy.ini @@ -0,0 +1,8 @@ +memory_limit = 512M +post_max_size = 512M +upload_max_filesize = 512M +upload_tmp_dir = /tmp + +request_order = GPC +session.gc_probability = 0 +session.auto_start = 0 diff --git a/legacy/locale/locale.gen b/legacy/locale/locale.gen new file mode 100644 index 000000000..8f214c08c --- /dev/null +++ b/legacy/locale/locale.gen @@ -0,0 +1,21 @@ +cs_CZ.UTF-8 UTF-8 +de_AT.UTF-8 UTF-8 +de_DE.UTF-8 UTF-8 +el_GR.UTF-8 UTF-8 +en_CA.UTF-8 UTF-8 +en_GB.UTF-8 UTF-8 +en_US.UTF-8 UTF-8 +es_ES.UTF-8 UTF-8 +fr_FR.UTF-8 UTF-8 +hr_HR.UTF-8 UTF-8 +hu_HU.UTF-8 UTF-8 +it_IT.UTF-8 UTF-8 +ja_JP.UTF-8 UTF-8 +ko_KR.UTF-8 UTF-8 +pl_PL.UTF-8 UTF-8 +pt_BR.UTF-8 UTF-8 +ru_RU.UTF-8 UTF-8 +sr_RS.UTF-8 UTF-8 +sr_RS@latin.UTF-8 UTF-8 +uk_UA.UTF-8 UTF-8 +zh_CN.UTF-8 UTF-8