diff --git a/.dockerignore b/.dockerignore index 3b429b802..c67b45e78 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,5 +2,6 @@ vendor/ docker/mariadb-data docker/redis-data docker/manticore-data -storage -resources +.env +storage/nzb +storage/covers diff --git a/.env.dist b/.env.dist new file mode 100644 index 000000000..1429c59d1 --- /dev/null +++ b/.env.dist @@ -0,0 +1,209 @@ +DB_CONNECTION=${DB_CONNECTION} +DB_HOST=${DB_HOST} +DB_PORT=${DB_PORT} +DB_ROOTPASSWORD=${DB_ROOTPASSWORD} +DB_SOCKET=${DB_SOCKET} +DB_USERNAME=${DB_USERNAME} +DB_PASSWORD=${DB_PASSWORD} +DB_DATABASE=${DB_DATABASE} + +COMPOSER_AUTH='${COMPOSER_AUTH}' + +MANTICORESEARCH_HOST=${MANTICORESEARCH_HOST} +MANTICORESEARCH_PORT=${MANTICORESEARCH_PORT} + +ELASTICSEARCH_HOST=${ELASTICSEARCH_HOST} +ELASTICSEARCH_PORT=${ELASTICSEARCH_PORT} +ELASTICSEARCH_SCHEME=${ELASTICSEARCH_SCHEME} +ELASTICSEARCH_USER=${ELASTICSEARCH_USER} +ELASTICSEARCH_PASS=${ELASTICSEARCH_PASS} +ELASTICSEARCH_LOGGING=${ELASTICSEARCH_LOGGING} +ELASTICSEARCH_ENABLED=${ELASTICSEARCH_ENABLED} + +NNTP_COMPRESSED_HEADERS=${NNTP_COMPRESSED_HEADERS} +USE_ALTERNATE_NNTP_SERVER=${USE_ALTERNATE_NNTP_SERVER} + +NNTP_USERNAME=${NNTP_USERNAME} +NNTP_PASSWORD=${NNTP_PASSWORD} +NNTP_SERVER=${NNTP_SERVER} +NNTP_PORT=${NNTP_PORT} +NNTP_CONNECTIONS=${NNTP_CONNECTIONS} +NNTP_SSLENABLED=${NNTP_SSLENABLED} +NNTP_SOCKET_TIMEOUT=${NNTP_SOCKET_TIMEOUT} + +NNTP_USERNAME_A=${NNTP_USERNAME_A} +NNTP_PASSWORD_A=${NNTP_PASSWORD_A} +NNTP_SERVER_A=${NNTP_SERVER_A} +NNTP_PORT_A=${NNTP_PORT_A} +NNTP_CONNECTIONS_A=${NNTP_CONNECTIONS_A} +NNTP_SSLENABLED_A=${NNTP_SSLENABLED_A} +NNTP_SOCKET_TIMEOUT_A=${NNTP_SOCKET_TIMEOUT_A} + +NN_MULTIPROCESSING_MAX_CHILD_TIME=${NN_MULTIPROCESSING_MAX_CHILD_TIME} + +ADMIN_USER=${ADMIN_USER} +ADMIN_PASS=${ADMIN_PASS} +ADMIN_EMAIL=${ADMIN_EMAIL} + +APP_NAME=${APP_NAME} +APP_ENV=${APP_ENV} +APP_DEBUG=${APP_DEBUG} +APP_TIMEZONE=${APP_TIMEZONE} +APP_URL=${APP_URL} + +APP_LOCALE=${APP_LOCALE} +APP_FALLBACK_LOCALE=${APP_FALLBACK_LOCALE} +APP_FAKER_LOCALE=${APP_FAKER_LOCALE} + +APP_MAINTENANCE_DRIVER=${APP_MAINTENANCE_DRIVER} +APP_MAINTENANCE_STORE=${APP_MAINTENANCE_STORE} + +BCRYPT_ROUNDS=${BCRYPT_ROUNDS} +APP_KEY=${APP_KEY} +LOG_CHANNEL=${LOG_CHANNEL} +LOG_STACK=${LOG_STACK} +PASSWORD_HASH=${PASSWORD_HASH} + +BROADCAST_CONNECTION=${BROADCAST_CONNECTION} +CACHE_STORE=${CACHE_STORE} +QUEUE_CONNECTION=${QUEUE_CONNECTION} + +REDIS_HOST=${REDIS_HOST} +REDIS_PASSWORD=${REDIS_PASSWORD} +REDIS_PORT=${REDIS_PORT} +REDIS_CLIENT=${REDIS_CLIENT} + +SESSION_DRIVER=${SESSION_DRIVER} +SESSION_DOMAIN=${SESSION_DOMAIN} +SESSION_SECURE_COOKIE=${SESSION_SECURE_COOKIE} +SESSION_ENCRYPT=${SESSION_ENCRYPT} +SESSION_COOKIE=${SESSION_COOKIE} +SESSION_PATH=${SESSION_PATH} + +MAIL_DRIVER=${MAIL_DRIVER} +MAIL_HOST=${MAIL_HOST} +MAIL_PORT=${MAIL_PORT} +MAIL_USERNAME=${MAIL_USERNAME} +MAIL_PASSWORD=${MAIL_PASSWORD} +MAIL_ENCRYPTION=${MAIL_ENCRYPTION} +MAIL_FROM_ADDRESS=${MAIL_FROM_ADDRESS} +MAIL_FROM_NAME=${MAIL_FROM_NAME} + +AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} +AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} +AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} +AWS_BUCKET=${AWS_BUCKET} + +PUSHER_APP_ID=${PUSHER_APP_ID} +PUSHER_APP_KEY=${PUSHER_APP_KEY} +PUSHER_APP_SECRET=${PUSHER_APP_SECRET} +PUSHER_APP_CLUSTER=${PUSHER_APP_CLUSTER} + +MIX_PUSHER_APP_KEY=${PUSHER_APP_KEY} +MIX_PUSHER_APP_CLUSTER=${PUSHER_APP_CLUSTER} + +NOCAPTCHA_ENABLED=${NOCAPTCHA_ENABLED} +NOCAPTCHA_SITEKEY=${NOCAPTCHA_SITEKEY} +NOCAPTCHA_SECRET=${NOCAPTCHA_SECRET} + +SCOUT_DRIVER=${SCOUT_DRIVER} +SCOUT_QUEUE=${SCOUT_QUEUE} + +ITEMS_PER_PAGE=${ITEMS_PER_PAGE} +ITEMS_PER_COVER_PAGE=${ITEMS_PER_COVER_PAGE} +MAX_PAGER_RESULTS=${MAX_PAGER_RESULTS} +ECHOCLI=${ECHOCLI} +RENAME_PAR2=${RENAME_PAR2} +ADD_PAR2=${ADD_PAR2} +RENAME_MUSIC_MEDIAINFO=${RENAME_MUSIC_MEDIAINFO} +CACHE_EXPIRY_SHORT=${CACHE_EXPIRY_SHORT} +CACHE_EXPIRY_MEDIUM=${CACHE_EXPIRY_MEDIUM} +CACHE_EXPIRY_LONG=${CACHE_EXPIRY_LONG} + +SSL_CAFILE=${SSL_CAFILE} +SSL_CAPATH=${SSL_CAPATH} +SSL_VERIFY_PEER=${SSL_VERIFY_PEER} +SSL_VERIFY_HOST=${SSL_VERIFY_HOST} +SSL_ALLOW_SELF_SIGNED=${SSL_ALLOW_SELF_SIGNED} + +SCRAPE_IRC_USERNAME=${SCRAPE_IRC_USERNAME} +SCRAPE_IRC_SERVER=${SCRAPE_IRC_SERVER} +SCRAPE_IRC_PORT=${SCRAPE_IRC_PORT} +SCRAPE_IRC_TLS=${SCRAPE_IRC_TLS} +SCRAPE_IRC_PASSWORD=${SCRAPE_IRC_PASSWORD} + +SMARTY_DEBUG=${SMARTY_DEBUG} +SMARTY_CACHING=${SMARTY_CACHING} +SMARTY_CACHE_LIFE=${SMARTY_CACHE_LIFE} +SMARTY_COMPILE_CHECK=${SMARTY_COMPILE_CHECK} +SMARTY_FORCE_COMPILE=${SMARTY_FORCE_COMPILE} +SMARTY_CACHE_DRIVER=${SMARTY_CACHE_DRIVER} + +TWITCH_CLIENT_ID=${TWITCH_CLIENT_ID} +TWITCH_CLIENT_SECRET=${TWITCH_CLIENT_SECRET} +IGDB_CACHE_LIFETIME=${IGDB_CACHE_LIFETIME} +TMDB_APIKEY=${TMDB_APIKEY} +TMDB_CACHE=${TMDB_CACHE} +TMDB_LOG=${TMDB_LOG} +TVDB_APIKEY=${TVDB_APIKEY} +TVDB_PIN=${TVDB_PIN} +GIANTBOMB_APIKEY=${GIANTBOMB_APIKEY} +ANIDB_APIKEY=${ANIDB_APIKEY} +FANARTTV_APIKEY=${FANARTTV_APIKEY} +OMDB_APIKEY=${OMDB_APIKEY} +TRAKTTV_APIKEY=${TRAKTTV_APIKEY} + +TEMP_UNRAR_PATH=${TEMP_UNRAR_PATH} +TEMP_UNZIP_PATH=${TEMP_UNZIP_PATH} + +VIEW_COMPILED_PATH=${VIEW_COMPILED_PATH} +UNRAR_PATH=${UNRAR_PATH} +UNZIP_PATH=${UNZIP_PATH} +FFMPEG_PATH=${FFMPEG_PATH} +LAME_PATH=${LAME_PATH} +MEDIAINFO_PATH=${MEDIAINFO_PATH} +TIIMEOUT_PATH=${TIIMEOUT_PATH} +MAGIC_FILE_PATH=${MAGIC_FILE_PATH} +COVERS_PATH=${COVERS_PATH} +PATH_TO_NZBS=${PATH_TO_NZBS} + +ASSET_URL=${ASSET_URL} + +TELESCOPE_DRIVER=${TELESCOPE_DRIVER} +TELESCOPE_ENABLED=${TELESCOPE_ENABLED} +TELESCOPE_FULL_IN_PRODUCTION=${TELESCOPE_FULL_IN_PRODUCTION} +TELESCOPE_CACHE_WATCHER=${TELESCOPE_CACHE_WATCHER} +TELESCOPE_COMMAND_WATCHER=${TELESCOPE_COMMAND_WATCHER} +TELESCOPE_DUMP_WATCHER=${TELESCOPE_DUMP_WATCHER} +TELESCOPE_EVENT_WATCHER=${TELESCOPE_EVENT_WATCHER} +TELESCOPE_EXCEPTION_WATCHER=${TELESCOPE_EXCEPTION_WATCHER} +TELESCOPE_JOB_WATCHER=${TELESCOPE_JOB_WATCHER} +TELESCOPE_LOG_WATCHER=${TELESCOPE_LOG_WATCHER} +TELESCOPE_MAIL_WATCHER=${TELESCOPE_MAIL_WATCHER} +TELESCOPE_MODEL_WATCHER=${TELESCOPE_MODEL_WATCHER} +TELESCOPE_NOTIFICATION_WATCHER=${TELESCOPE_NOTIFICATION_WATCHER} +TELESCOPE_QUERY_WATCHER=${TELESCOPE_QUERY_WATCHER} +TELESCOPE_REDIS_WATCHER=${TELESCOPE_REDIS_WATCHER} +TELESCOPE_REQUEST_WATCHER=${TELESCOPE_REQUEST_WATCHER} +TELESCOPE_RESPONSE_SIZE_LIMIT=${TELESCOPE_RESPONSE_SIZE_LIMIT} +TELESCOPE_GATE_WATCHER=${TELESCOPE_GATE_WATCHER} +TELESCOPE_SCHEDULE_WATCHER=${TELESCOPE_SCHEDULE_WATCHER} + +HORIZON_PREFIX=${HORIZON_PREFIX} + +POSTMARK_TOKEN=${POSTMARK_TOKEN} + +PURGE_INACTIVE_USERS=${PURGE_INACTIVE_USERS} + +OTP_ENABLED=${OTP_ENABLED} + +FLARE_KEY=${FLARE_KEY} + +CHECK_PASSWORDED_RARS=${CHECK_PASSWORDED_RARS} +DELETE_PASSWORDED_RELEASES=${DELETE_PASSWORDED_RELEASES} +DELETE_POSSIBLE_PASSWORDED_RELEASES=${DELETE_POSSIBLE_PASSWORDED_RELEASES} +EXTRACT_USING_RARINFO=${EXTRACT_USING_RARINFO} +PRIVATE_PROFILES=${PRIVATE_PROFILES} +STORE_USER_IP=${STORE_USER_IP} + +FORUM_FRONTEND_ENABLED=${FORUM_FRONTEND_ENABLED} diff --git a/.env.example b/.env.example index 6a75a3572..bbdf538e4 100644 --- a/.env.example +++ b/.env.example @@ -157,6 +157,16 @@ TEMP_UNRAR_PATH='/var/www/nntmux/resources/tmp/unrar/' TEMP_UNZIP_PATH='/var/www/nntmux/resources/tmp/unzip/' VIEW_COMPILED_PATH=/var/www/NNTmux/storage/framework/views +UNRAR_PATH= +UNZIP_PATH= +PATH_TO_NZBS= +FFMPEG_PATH= +LAME_PATH= +MEDIAINFO_PATH= +TIIMEOUT_PATH= +MAGIC_FILE_PATH= +COVERS_PATH= + ASSET_URL= TELESCOPE_DRIVER=database @@ -189,20 +199,11 @@ OTP_ENABLED=false FLARE_KEY= -UNRAR_PATH= -UNZIP_PATH= CHECK_PASSWORDED_RARS=false DELETE_PASSWORDED_RELEASES=false DELETE_POSSIBLE_PASSWORDED_RELEASES=false EXTRACT_USING_RARINFO=false -PATH_TO_NZBS= PRIVATE_PROFILES=true STORE_USER_IP=false -FFMPEG_PATH= -LAME_PATH= -MEDIAINFO_PATH= -TIIMEOUT_PATH= -MAGIC_FILE_PATH= -COVERS_PATH= FORUM_FRONTEND_ENABLED=false diff --git a/.gitignore b/.gitignore index fea29a6d6..2a93f3a32 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ failed-login.log php_errors.log php-errors.log test.php +.php-cs-fixer.cache # Editor temp files *# @@ -39,4 +40,4 @@ node_modules/ # Stores VSCode versions used for testing VSCode extensions .vscode-test -/.phpunit.cache \ No newline at end of file +/.phpunit.cache diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..b618848fc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,73 @@ + +FROM composer:latest AS composer-base +FROM dunglas/frankenphp:1-php8.3 +LABEL maintainer="PyRowMan" +ENV SERVER_NAME=:80 +ARG MYSQL_CLIENT="mariadb-client" +ARG SEVENZIP_VERSION=2407 + +WORKDIR /app + + +COPY --from=node:21 /usr/local/ /usr/local/ +COPY --from=composer-base --link /usr/bin/composer /usr/bin/composer + +RUN apt update \ + && apt install -y --no-install-recommends \ + unrar-free 7zip lame libcap2-bin python3 gettext-base \ + curl zip unzip git nano bash-completion sudo wget tmux time fonts-powerline \ + gnupg libpng-dev dnsutils jq htop iputils-ping net-tools ffmpeg \ + jpegoptim webp optipng pngquant libavif-bin watch iproute2 nmon \ + libonig-dev libxml2-dev libicu-dev libjpeg-dev libfreetype6-dev libxslt-dev $MYSQL_CLIENT libcurl4-openssl-dev \ + && wget https://mediaarea.net/repo/deb/repo-mediaarea_1.0-24_all.deb \ + && dpkg -i repo-mediaarea_1.0-24_all.deb \ + && apt update \ + && apt install -y libmediainfo0v5 mediainfo libzen0v5 +RUN install-php-extensions imagick/imagick@master +RUN docker-php-ext-install \ + bcmath \ + exif \ + gd \ + intl \ + pdo_mysql \ + sockets \ + pcntl \ + && pecl install redis \ + && docker-php-ext-enable redis \ + && apt clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +# Determine ARCH and download and extract the appropriate version of 7-Zip +RUN ARCH="$(dpkg --print-architecture)" && \ + if [ "$ARCH" = "amd64" ]; then \ + SZIP_URL="https://www.7-zip.org/a/7z$SEVENZIP_VERSION-linux-x64.tar.xz"; \ + fi && \ + if [ "$ARCH" = "arm64" ]; then \ + SZIP_URL="https://www.7-zip.org/a/7z$SEVENZIP_VERSION-linux-arm64.tar.xz"; \ + fi && \ + wget "$SZIP_URL" -O /tmp/7z.tar.xz && \ + tar -xf /tmp/7z.tar.xz -C /tmp/ && \ + mv /tmp/7zz /usr/bin/7zz && \ + rm -f /tmp/7z.tar.xz && rm -f /tmp/7zzs + +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" +COPY ./docker/8.3/php.ini "$PHP_INI_DIR/conf.d/custom-conf.ini" + +COPY --chmod=755 ./docker-entrypoint.sh /usr/local/bin/docker-entrypoint + +COPY . /app + +RUN rm -Rf tests/ + +RUN composer install + +RUN chmod -R 755 /app/vendor/ +RUN chmod -R 777 /app/storage/ +RUN chmod -R 777 /app/resources/ +RUN chmod -R 777 /app/public/ + +EXPOSE 80 + +CMD ["--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"] +ENTRYPOINT ["docker-entrypoint"] + + diff --git a/app/Console/Commands/InstallNntmux.php b/app/Console/Commands/InstallNntmux.php index 594e902c3..6e5553513 100644 --- a/app/Console/Commands/InstallNntmux.php +++ b/app/Console/Commands/InstallNntmux.php @@ -14,7 +14,7 @@ class InstallNntmux extends Command * * @var string */ - protected $signature = 'nntmux:install'; + protected $signature = 'nntmux:install {--y|yes : Skip confirmation prompts and proceed with installation}'; /** * The console command description. @@ -35,45 +35,53 @@ class InstallNntmux extends Command public function handle(): void { - $error = false; - - if ($this->confirm('Are you sure you want to install NNTmux? This will wipe your database!!')) { - if (File::exists(base_path().'/_install/install.lock')) { - if ($this->confirm('Do you want to remove install.lock file so you can continue with install?')) { - $this->info('Removing install.lock file so we can continue with install process'); + $yesMode = $this->option('yes'); + if (File::exists(base_path().'/_install/install.lock')) { + if ($yesMode) { + $this->info('Install is locked. The file "install.lock" is present. Use interactive mode to remove it.'); + exit; + } else { + if ($this->confirm('Install is locked. Do you want to remove the "install.lock" file to continue?')) { + $this->info('Removing install.lock file so we can continue with install process...'); $remove = Process::timeout(600)->run('rm _install/install.lock'); echo $remove->output(); echo $remove->errorOutput(); } else { - $this->info('Not removing install.lock, stopping install process'); + $this->info('Installation aborted. The file "install.lock" was not removed.'); exit; } } - $this->info('Migrating tables and seeding them with initial data'); - if (config('app.env') !== 'production') { - $this->call('migrate:fresh', ['--seed' => true]); - } else { - $this->call('migrate:fresh', ['--force' => true, '--seed' => true]); - } - - $paths = $this->updatePaths(); - if ($paths !== false) { - $this->info('Paths checked successfully'); - } - - if (! $error && $this->addAdminUser()) { - File::put(base_path().'/_install/install.lock', 'application install locked on '.now()); - $this->info('Generating application key'); - $this->call('key:generate', ['--force' => true]); - $this->info('NNTmux installation completed successfully'); - exit(); - } - - $this->error('NNTmux installation failed. Fix reported problems and try again'); - } else { - $this->info('Stopping install process'); - exit; } + + if (! $yesMode) { + if (! $this->confirm('Are you sure you want to install NNTmux? This will wipe your database!!')) { + $this->info('Installation aborted by user.'); + exit; + } + } + + $this->info('Migrating tables and seeding them with initial data'); + if (config('app.env') !== 'production') { + $this->call('migrate:fresh', ['--seed' => true]); + } else { + $this->call('migrate:fresh', ['--force' => true, '--seed' => true]); + } + + $paths = $this->updatePaths(); + if ($paths !== false) { + $this->info('Paths checked successfully'); + } + + if ($this->addAdminUser()) { + File::put(base_path().'/_install/install.lock', 'application install locked on '.now()); + $this->info('Generating application key'); + $this->call('key:generate', ['--force' => true]); + $this->info('NNTmux installation completed successfully'); + exit(); + } + + $this->error('NNTmux installation failed. Fix reported problems and try again'); + } /** @@ -118,6 +126,7 @@ class InstallNntmux extends Command if (! File::isWritable($zip_path)) { $this->warn($zip_path.' is not writable. Please fix folder permissions'); + return false; } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..76b4ac1c9 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,173 @@ +services: + webapp: + build: + context: . + dockerfile: Dockerfile + image: pyrowman/nntmux + extra_hosts: + - 'host.docker.internal:host-gateway' + ports: + - '${APP_PORT:-80}:80' + environment: + TZ: ${APP_TIMEZONE} + healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:80" ] + interval: 10s + timeout: 5s + retries: 5 + env_file: + - .env + volumes: + - 'install:/app/_install' + - 'storage:/app/storage' +# - 'resources:/var/www/html/resources' + networks: + - nntmux + depends_on: + - mariadb + - redis + - mailpit + - elasticsearch + - manticore + worker: + command: > + sh -c "php artisan tmux-ui:start & php artisan horizon" + image: pyrowman/nntmux + extra_hosts: + - 'host.docker.internal:host-gateway' + tty: true + environment: + TZ: ${APP_TIMEZONE} + env_file: + - .env + volumes: + - 'install:/app/_install' + - 'storage:/app/storage' + networks: + - nntmux + depends_on: + webapp: + condition: service_healthy + scheduler: + image: pyrowman/nntmux + extra_hosts: + - 'host.docker.internal:host-gateway' + tty: true + env_file: + - .env + environment: + TZ: ${APP_TIMEZONE} + volumes: + - 'install:/app/_install' + - 'storage:/app/storage' + networks: + - nntmux + depends_on: + webapp: + condition: service_healthy + command: > + sh -c "while [ true ]; do php artisan schedule:run; sleep 60;done" + mariadb: + image: 'mariadb:11' + ports: + - '${FORWARD_DB_PORT:-3306}:3306' + environment: + TZ: ${APP_TIMEZONE} + MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' + MYSQL_ROOT_HOST: '%' + MYSQL_DATABASE: '${DB_DATABASE}' + MYSQL_USER: '${DB_USERNAME}' + MYSQL_PASSWORD: '${DB_PASSWORD}' + MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' + command: + --max_allowed_packet=128M + --group_concat_max_len=16384 + --max_connections=200 + volumes: + - 'mariadb:/var/lib/mysql' + - './vendor/laravel/sail/database/mariadb/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh' + networks: + - nntmux + healthcheck: + test: + - CMD + - mysqladmin + - ping + - '-p${DB_PASSWORD}' + retries: 3 + timeout: 5s + redis: + image: 'redis:alpine' + ports: + - '${FORWARD_REDIS_PORT:-6379}:6379' + environment: + TZ: ${APP_TIMEZONE} + volumes: + - 'redis:/data' + networks: + - nntmux + healthcheck: + test: + - CMD + - redis-cli + - ping + retries: 3 + timeout: 5s + manticore: + image: manticoresearch/manticore + environment: + TZ: ${APP_TIMEZONE} + EXTRA: 1 # Activates extra features + restart: always + ports: + - 9306:9306 + - 9308:9308 + ulimits: + nproc: 65535 + nofile: + soft: 65535 + hard: 65535 + memlock: + soft: -1 + hard: -1 + volumes: + - 'manticore:/var/lib/manticore' +# - ./misc/manticoresearch/manticore.conf:/etc/manticoresearch/manticore.conf + networks: + - nntmux + mailpit: + image: 'axllent/mailpit:latest' + ports: + - '${FORWARD_MAILPIT_PORT:-1025}:1025' + - '${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025' + networks: + - nntmux + elasticsearch: + image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0 + environment: + - TZ=${APP_TIMEZONE} + - discovery.type=single-node + - xpack.security.enabled=false + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + ports: + - 9200:9200 + - 9300:9300 + volumes: + - elasticsearch:/usr/share/elasticsearch/data + networks: + - nntmux + deploy: + resources: + limits: + memory: 1g +networks: + nntmux: + driver: bridge +volumes: + mariadb: + redis: + elasticsearch: + manticore: + storage: + resources: + install: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 000000000..6e456e4d3 --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,94 @@ +#!/bin/sh +set -e +# Create .env file if it doesn't exist +if [ ! -f .env ]; then + echo "Creating .env file from environment variables..." + envsubst < .env.dist > .env +fi +if [ "$1" != 'php' ] && [ "$1" != 'sh' ]; then + # Install dependencies if not already installed + if [ ! -d 'vendor/' ]; then + echo "Installing dependencies via Composer..." + composer install --prefer-dist --no-progress --no-interaction + fi + + + # Check and wait for the database to be ready + if grep -q ^DB_HOST= .env; then + echo "Waiting for the database to be ready..." + ATTEMPTS_LEFT_TO_REACH_DATABASE=60 + until [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ] || DATABASE_ERROR=$(php artisan db:show 2>&1); do + if [ $? -ne 0 ]; then + # Stop attempting in case of an error + ATTEMPTS_LEFT_TO_REACH_DATABASE=$((ATTEMPTS_LEFT_TO_REACH_DATABASE - 1)) + echo "Database not ready yet. Attempts left: $ATTEMPTS_LEFT_TO_REACH_DATABASE." + sleep 1 + else + break + fi + done + + if [ $ATTEMPTS_LEFT_TO_REACH_DATABASE -eq 0 ]; then + echo "Failed to connect to the database:" + echo "$DATABASE_ERROR" + exit 1 + else + echo "Database is now ready." + fi + fi + + if [ ! -f '_install/install.lock' ]; then + echo "Creating folders structure" + mkdir -p /app/storage/app/public + mkdir -p "$COVERS_PATH/anime" + mkdir -p "$COVERS_PATH/audio" + mkdir -p "$COVERS_PATH/audiosample" + mkdir -p "$COVERS_PATH/book" + mkdir -p "$COVERS_PATH/console" + mkdir -p "$COVERS_PATH/games" + mkdir -p "$COVERS_PATH/movies" + mkdir -p "$COVERS_PATH/music" + mkdir -p "$COVERS_PATH/preview" + mkdir -p "$COVERS_PATH/sample" + mkdir -p "$COVERS_PATH/tvrage" + mkdir -p "$COVERS_PATH/tvshows" + mkdir -p "$COVERS_PATH/video" + mkdir -p "$COVERS_PATH/xxx" + mkdir -p "$PATH_TO_NZBS" + mkdir -p "$TEMP_UNRAR_PATH" + mkdir -p "$TEMP_UNZIP_PATH" + # Set permissions for storage and bootstrap/cache directories + echo "Setting permissions on storage and bootstrap/cache directories..." + chmod -R 775 bootstrap/cache + chmod -R 777 storage resources + chown -R www-data:www-data storage bootstrap/cache resources + + echo "Clearing application cache..." + php artisan cache:clear + php artisan config:clear + php artisan route:clear + php artisan view:clear + + echo "Caching configuration and routes..." + php artisan config:cache + php artisan route:cache + + # Run Laravel-specific post-installation commands + echo "NNTmux installation..." + php artisan nntmux:install --yes + + if [ "${ELASTICSEARCH_ENABLED}" == "true" ]; then + echo "Elasticsearch initialisation" + php artisan nntmux:create-es-indexes + php artisan nntmux:populate --elastic --releases + php artisan nntmux:populate --elastic --predb + else + echo "Manticore initialisation" + php artisan nntmux:populate --manticore --releases + php artisan nntmux:populate --manticore --predb + fi + fi +fi + +# Run the PHP entry point with arguments +exec docker-php-entrypoint "$@" diff --git a/resources/views/components/application-logo.blade.php b/resources/views/components/application-logo.blade.php new file mode 100644 index 000000000..33f8b9aac --- /dev/null +++ b/resources/views/components/application-logo.blade.php @@ -0,0 +1,4 @@ + + + +