V3 - The big one #71

Merged
rogs merged 31 commits from v3 into master 2024-12-30 11:01:29 -03:00
2 changed files with 727 additions and 628 deletions
Showing only changes of commit 09008c82ee - Show all commits

768
docs.org
View File

@ -6,37 +6,24 @@
:PROPERTIES:
:ID: faf95c8a-9133-4072-8544-0ef456a67611
:END:
- [[#welcome-message][Welcome message]]
- [[#constants-and-configuration][Constants and Configuration]]
- [[#functions][Functions]]
- [[#message-formatting][Message formatting]]
- [[#check-the-dependencies][Check the dependencies]]
- [[#running-services-location][Running services location]]
- [[#verify-all-the-dependencies][Verify all the dependencies]]
- [[#gather-all-the-required-information][Gather all the required information]]
- [[#checking-install-location][Checking install location]]
- [[#setting-the-correct-user][Setting the correct user]]
- [[#media-directory][Media directory]]
- [[#setting-perferred-media-service][Setting perferred media service]]
- [[#setting-the-vpn][Setting the VPN]]
- [[#installing-yams][Installing YAMS]]
- [[#copy-the-docker-compose-file-to-the-install-location][Copy the docker-compose file to the install location]]
- [[#set-puid-pgid-media-folder-media-service-config-folder-and-vpn-on-the-yams-scripts][Set PUID, PGID, Media Folder, Media Service, Config folder and VPN on the YAMS scripts]]
- [[#set-the-configuration-for-the-yams-binary][Set the configuration for the YAMS binary]]
- [[#success-message][Success message!]]
- [[#final-steps][Final steps]]
- [[#install-the-yams-cli][Install the YAMS CLI]]
- [[#set-the-correct-permissions-to-the-media-and-install-directories][Set the correct permissions to the media and install directories]]
- [[#create-the-config-directory][Create the config directory]]
- [[#display-closing-message][Display closing message]]
- [[#directory-handling][Directory Handling]]
- [[#check-dependencies][Check Dependencies]]
- [[#service-configuration][Service Configuration]]
- [[#file-operations][File Operations]]
- [[#script-execution][Script Execution]]
- [[#verify-prerequisites][Verify Prerequisites]]
- [[#installation-process][Installation Process]]
- [[#display-closing-message][Display Closing Message]]
* Welcome message
:PROPERTIES:
:ID: 525c03eb-cab9-44f8-8cc5-e5ec9035a938
:END:
This is just a welcome message for the script
#+begin_src bash
#!/bin/bash
set -euo pipefail
@ -64,265 +51,204 @@ echo "===================================================="
echo ""
#+end_src
* Constants and Configuration
:PROPERTIES:
:ID: new-constants-section
:END:
#+begin_src bash
# Constants
readonly DEFAULT_INSTALL_DIR="/opt/yams"
readonly DEFAULT_MEDIA_DIR="/srv/media"
readonly SUPPORTED_MEDIA_SERVICES=("jellyfin" "emby" "plex")
readonly DEFAULT_MEDIA_SERVICE="jellyfin"
readonly DEFAULT_VPN_SERVICE="protonvpn"
readonly MEDIA_SUBDIRS=("tv" "movies" "music" "books" "downloads" "blackhole")
# Color codes
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m' # No Color
# Dependencies
readonly REQUIRED_COMMANDS=("curl" "docker" "docker" "sed" "awk")
#+end_src
* Functions
:PROPERTIES:
:ID: 111a7df4-08f5-4e6c-a799-dd822c5d030e
:END:
To make development easier, we declare some functions that are going to be used a lot later
** Message formatting
:PROPERTIES:
:ID: 61387bd4-2ecf-44fe-ac69-dc6347c0d1b8
:END:
Both of these functions format the message in different colors, depending on what the message means
*** Success
:PROPERTIES:
:ID: ec8f113c-43f9-4585-a1b5-8c7ec4e84bb2
:END:
#+begin_src bash
send_success_message() {
echo -e $(printf "\e[32m$1\e[0m")
log_success() {
echo -e "${GREEN}$1${NC}"
}
log_error() {
echo -e "${RED}$1${NC}" >&2
exit 1
}
log_warning() {
echo -e "${YELLOW}$1${NC}"
}
log_info() {
echo "$1"
}
#+end_src
*** Error
** Directory Handling
:PROPERTIES:
:ID: 1a6cd951-c9ce-46fc-8953-f5e206f7cd23
:ID: new-directory-section
:END:
Error is basically the same as before, but it ~exit 255~ to finish the execution.
#+begin_src bash
send_error_message() {
echo -e $(printf "\e[31m$1\e[0m")
exit 255
create_and_verify_directory() {
local dir="$1"
local dir_type="$2"
if [ ! -d "$dir" ]; then
echo "The directory \"$dir\" does not exist. Attempting to create..."
if mkdir -p "$dir"; then
log_success "Directory $dir created ✅"
else
log_error "Failed to create $dir_type directory at \"$dir\". Check permissions ❌"
fi
fi
if [ ! -w "$dir" ] || [ ! -r "$dir" ]; then
log_error "Directory \"$dir\" is not writable or readable. Check permissions ❌"
fi
}
setup_directory_structure() {
local media_dir="$1"
create_and_verify_directory "$media_dir" "media"
for subdir in "${MEDIA_SUBDIRS[@]}"; do
create_and_verify_directory "$media_dir/$subdir" "media subdirectory"
done
}
verify_user_permissions() {
local username="$1"
local directory="$2"
if ! id -u "$username" &>/dev/null; then
log_error "User \"$username\" doesn't exist!"
fi
if ! sudo -u "$username" test -w "$directory"; then
log_error "User \"$username\" doesn't have write permissions to \"$directory\""
fi
}
#+end_src
** Check the dependencies
** Check Dependencies
:PROPERTIES:
:ID: e7d01eeb-c7ef-42ff-b60d-010be30bc6a8
:END:
This function verifies that the dependencies are installed. ~Docker~ and ~Docker Compose~ are required
for YAMS to work.
#+begin_src bash
check_dependencies() {
if command -v docker &> /dev/null; then
send_success_message "docker exists ✅ "
if docker compose version &> /dev/null; then
send_success_message "docker compose exists ✅ "
else
echo -e $(printf "\e[31m ⚠️ docker compose not found! ⚠️\e[0m")
read -p "Do you want YAMS to install Docker Compose? IT ONLY WORKS ON DEBIAN AND UBUNTU! (y/N) [Default = n]: " install_docker
install_docker=${install_docker:-"n"}
if [ "$install_docker" == "y" ]; then
bash ./docker.sh
else
send_error_message "Install Docker Compose and come back later!"
# Check for required commands
for cmd in "${REQUIRED_COMMANDS[@]}"; do
if ! command -v "$cmd" &> /dev/null; then
log_error "Required command '$cmd' not found!"
fi
fi
else
echo -e $(printf "\e[31m ⚠️ docker not found! ⚠️\e[0m")
read -p "Do you want YAMS to install Docker and Docker Compose? IT ONLY WORKS ON DEBIAN AND UBUNTU! (y/N) [Default = n]: " install_docker
install_docker=${install_docker:-"n"}
if [ "$install_docker" == "y" ]; then
bash ./docker.sh
else
send_error_message "Install Docker and Docker Compose and come back later!"
fi
fi
}
#+end_src
** Running services location
:PROPERTIES:
:ID: 53213557-edfe-4da7-88c0-e0e202429116
:END:
This function just displays the locations for every container so the user can access to it when YAMS
finish installing.
#+begin_src bash
running_services_location() {
host_ip=$(hostname -I | awk '{ print $1 }')
services=(
"qBittorrent:8081"
"SABnzbd:8080"
"Radarr:7878"
"Sonarr:8989"
"Lidarr:8686"
"Readarr:8787"
"Prowlarr:9696"
"Bazarr:6767"
"$media_service:$media_service_port"
"Portainer:9000"
)
echo -e "Service URLs:"
for service in "${services[@]}"; do
service_name="${service%%:*}"
service_port="${service##*:}"
echo "$service_name: http://$host_ip:$service_port/"
done
# Check Docker
if command -v docker &> /dev/null; then
log_success "docker exists ✅"
if docker compose version &> /dev/null; then
log_success "docker compose exists ✅"
return 0
fi
fi
log_warning "⚠️ Docker/Docker Compose not found! ⚠️"
read -p "Install Docker and Docker Compose? Only works on Debian/Ubuntu (y/N) [Default = n]: " install_docker
install_docker=${install_docker:-"n"}
if [ "${install_docker,,}" = "y" ]; then
bash ./docker.sh
else
log_error "Please install Docker and Docker Compose first"
fi
}
#+end_src
* Verify all the dependencies
** Service Configuration
:PROPERTIES:
:ID: e945d5a8-5142-41fe-8175-96de7aa84cf2
:ID: new-service-section
:END:
#+begin_src bash
echo "Checking prerequisites..."
configure_media_service() {
log_info "\nTime to choose your media service."
log_info "Your media service is responsible for serving your files to your network."
log_info "Supported media services:"
log_info "- jellyfin (recommended, easier)"
log_info "- emby"
log_info "- plex (advanced, always online)"
check_dependencies
if [[ "$EUID" = 0 ]]; then
send_error_message "YAMS has to run without sudo! Please, run it again with regular permissions"
fi
#+end_src
* Gather all the required information
:PROPERTIES:
:ID: 438cecef-2bd6-4d7c-b429-6c674ae311d9
:END:
** Checking install location
:PROPERTIES:
:ID: fff12355-9d79-40fe-a540-cfba2a176a3e
:END:
#+begin_src bash
default_install_directory="/opt/yams"
read -p "Where do you want to install the docker-compose file? [$default_install_directory]: " install_directory
install_directory=${install_directory:-$default_install_directory}
if [ ! -d "$install_directory" ]; then
echo "The directory \"$install_directory\" does not exists. Attempting to create..."
if mkdir -p "$install_directory"; then
send_success_message "Directory $install_directory created ✅"
else
send_error_message "There was an error creating the installation directory at \"$install_directory\". Make sure you have the necessary permissions ❌"
fi
fi
if [ ! -w "$install_directory" ] || [ ! -r "$install_directory" ]; then
send_error_message "The directory \"$install_directory\" is not writable or readable by the current user. Set the correct permissions or try a different directory" ❌
fi
filename="$install_directory/docker-compose.yaml"
custom_file_filename="$install_directory/docker-compose.custom.yaml"
env_file="$install_directory/.env"
#+end_src
** Setting the correct user
:PROPERTIES:
:ID: 7428d7b7-aec5-4638-b370-84e9055fb412
:END:
#+begin_src bash
read -p "What's the user that is going to own the media server files? [$USER]: " username
username=${username:-$USER}
if id -u "$username" &>/dev/null; then
puid=$(id -u "$username");
pgid=$(id -g "$username");
else
send_error_message "The user \"$username\" doesn't exist!"
fi
#+end_src
** Media directory
:PROPERTIES:
:ID: 9726dead-8833-4f23-98b8-2790d72605de
:END:
#+begin_src bash
read -p "Please, input your media directory [/srv/media]: " media_directory
media_directory=${media_directory:-"/srv/media"}
read -p "Are you sure your media directory is \"$media_directory\"? (y/N) [Default = n]: " media_directory_correct
media_directory_correct=${media_directory_correct:-"n"}
if [ ! -d "$media_directory" ]; then
echo "The directory \"$media_directory\" does not exists. Attempting to create..."
if mkdir -p "$media_directory"; then
send_success_message "Directory $media_directory created ✅"
else
send_error_message "There was an error creating the installation directory at \"$media_directory\". Make sure you have the necessary permissions ❌"
fi
fi
if [ "$media_directory_correct" == "n" ]; then
send_error_message "Media directory is not correct. Please fix it and run the script again ❌"
fi
#+end_src
** Setting perferred media service
:PROPERTIES:
:ID: 3af8dbed-3a88-4739-a721-6434993c0b67
:END:
#+begin_src bash
echo -e "\n\n\nTime to choose your media service."
echo "Your media service is responsible for serving your files to your network."
echo "By default, YAMS supports 3 media services:"
echo "- jellyfin (recommended, easier)"
echo "- emby"
echo "- plex (advanced, always online)"
read -p "Choose your media service [jellyfin]: " media_service
media_service=${media_service:-"jellyfin"}
read -p "Choose your media service [$DEFAULT_MEDIA_SERVICE]: " media_service
media_service=${media_service:-$DEFAULT_MEDIA_SERVICE}
media_service=$(echo "$media_service" | awk '{print tolower($0)}')
media_service_port=8096
if [[ ! " ${SUPPORTED_MEDIA_SERVICES[@]} " =~ " ${media_service} " ]]; then
log_error "\"$media_service\" is not supported by YAMS"
fi
# Set media service port
if [ "$media_service" == "plex" ]; then
media_service_port=32400
fi
if echo "emby plex jellyfin" | grep -qw "$media_service"; then
echo -e "\nYAMS is going to install \"$media_service\" on port \"$media_service_port\""
else
send_error_message "\"$media_service\" is not supported by YAMS. Are you sure you chose the correct service?"
media_service_port=8096
fi
#+end_src
** Setting the VPN
:PROPERTIES:
:ID: 1da4fe67-ee20-4b70-8f36-4a9f7161b6ca
:END:
log_success "\nYAMS will install \"$media_service\" on port \"$media_service_port\""
#+begin_src bash
echo -e "\nTime to set up the VPN."
echo "You can check the supported VPN list here: https://yams.media/advanced/vpn."
# Export for use in other functions
export media_service media_service_port
}
read -p "Do you want to configure a VPN? (Y/n) [Default = y]: " setup_vpn
configure_vpn() {
log_info "\nTime to set up the VPN."
log_info "Supported VPN providers: https://yams.media/advanced/vpn"
read -p "Configure VPN? (Y/n) [Default = y]: " setup_vpn
setup_vpn=${setup_vpn:-"y"}
if [ "$setup_vpn" == "y" ]; then
read -p "What's your VPN service? (with spaces) [protonvpn]: " vpn_service
vpn_service=${vpn_service:-"protonvpn"}
if [ "${setup_vpn,,}" != "y" ]; then
export setup_vpn="n"
return 0
fi
echo -e "\nYou should read $vpn_service's documentation in case it has different configurations for username and password."
echo "The documentation for $vpn_service is here: https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/${vpn_service// /-}.md"
read -p "VPN service? (with spaces) [$DEFAULT_VPN_SERVICE]: " vpn_service
vpn_service=${vpn_service:-$DEFAULT_VPN_SERVICE}
read -p "What's your VPN username? (without spaces): " vpn_user
log_info "\nPlease check $vpn_service's documentation for specific configuration:"
log_info "https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/${vpn_service// /-}.md"
read -p "VPN username (without spaces): " vpn_user
[ -z "$vpn_user" ] && log_error "VPN username cannot be empty"
# Use hidden input for password
unset vpn_password
charcount=0
prompt="What's your VPN password? (if you are using mullvad, just enter your username again): "
while IFS= read -p "$prompt" -r -s -n 1 char
do
if [[ $char == $'\0' ]]
then
prompt="VPN password (if using mullvad, enter username again): "
while IFS= read -p "$prompt" -r -s -n 1 char; do
if [[ $char == $'\0' ]]; then
break
fi
if [[ $char == $'\177' ]]; then
@ -340,176 +266,238 @@ if [ "$setup_vpn" == "y" ]; then
fi
done
echo
fi
echo "Configuring the docker-compose file for the user \"$username\" on \"$install_directory\"..."
#+end_src
[ -z "$vpn_password" ] && log_error "VPN password cannot be empty"
* Installing YAMS
:PROPERTIES:
:ID: 44e5f3f1-3ae7-4f88-ba96-8149c9980fb2
:END:
** Copy the docker-compose file to the install location
:PROPERTIES:
:ID: 09018e25-ed48-46e9-85c3-586c37844c11
:END:
# Export for use in other functions
export vpn_service vpn_user vpn_password setup_vpn
}
#+begin_src bash
copy_files=(
"docker-compose.example.yaml:$filename"
".env.example:$env_file"
"docker-compose.custom.yaml:$custom_file_filename"
running_services_location() {
local host_ip
host_ip=$(hostname -I | awk '{ print $1 }')
local -A services=(
["qBittorrent"]="8081"
["SABnzbd"]="8080"
["Radarr"]="7878"
["Sonarr"]="8989"
["Lidarr"]="8686"
["Readarr"]="8787"
["Prowlarr"]="9696"
["Bazarr"]="6767"
["$media_service"]="$media_service_port"
["Portainer"]="9000"
)
for file_mapping in "${copy_files[@]}"; do
source_file="${file_mapping%%:*}"
destination_file="${file_mapping##*:}"
echo -e "Service URLs:"
for service in "${!services[@]}"; do
echo "$service: http://$host_ip:${services[$service]}/"
done
}
echo -e "\nCopying $source_file to $destination_file..."
if cp "$source_file" "$destination_file"; then
send_success_message "$source_file was copied successfuly! ✅"
get_user_info() {
read -p "User to own the media server files? [$USER]: " username
username=${username:-$USER}
if id -u "$username" &>/dev/null; then
puid=$(id -u "$username")
pgid=$(id -g "$username")
else
send_error_message "Failed to copy $source_file to $destination_file. Ensure your user ($USER) has the necessary permissions ❌"
log_error "User \"$username\" doesn't exist!"
fi
export username puid pgid
}
get_installation_paths() {
read -p "Installation directory? [$DEFAULT_INSTALL_DIR]: " install_directory
install_directory=${install_directory:-$DEFAULT_INSTALL_DIR}
create_and_verify_directory "$install_directory" "installation"
read -p "Media directory? [$DEFAULT_MEDIA_DIR]: " media_directory
media_directory=${media_directory:-$DEFAULT_MEDIA_DIR}
read -p "Are you sure your media directory is \"$media_directory\"? (y/N) [Default = n]: " media_directory_correct
media_directory_correct=${media_directory_correct:-"n"}
if [ "${media_directory_correct,,}" != "y" ]; then
log_error "Media directory is not correct. Please fix it and run the script again ❌"
fi
setup_directory_structure "$media_directory"
verify_user_permissions "$username" "$media_directory"
export install_directory media_directory
}
#+end_src
** File Operations
:PROPERTIES:
:ID: new-file-operations-section
:END:
#+begin_src bash
copy_configuration_files() {
local -A files=(
["docker-compose.example.yaml"]="docker-compose.yaml"
[".env.example"]=".env"
["docker-compose.custom.yaml"]="docker-compose.custom.yaml"
)
for src in "${!files[@]}"; do
local dest="$install_directory/${files[$src]}"
log_info "\nCopying $src to $dest..."
if cp "$src" "$dest"; then
log_success "$src copied successfully ✅"
else
log_error "Failed to copy $src to $dest. Check permissions ❌"
fi
done
#+end_src
}
#+RESULTS:
update_configuration_files() {
local filename="$install_directory/docker-compose.yaml"
local env_file="$install_directory/.env"
local yams_script="yams"
** Set PUID, PGID, Media Folder, Media Service, Config folder and VPN on the YAMS scripts
:PROPERTIES:
:ID: 3d169001-f0f7-477f-a954-0460484f4b43
:END:
# Update .env file
log_info "Updating environment configuration..."
sed -i -e "s|<your_PUID>|$puid|g" \
-e "s|<your_PGID>|$pgid|g" \
-e "s|<media_directory>|$media_directory|g" \
-e "s|<media_service>|$media_service|g" \
-e "s|<install_directory>|$install_directory|g" \
-e "s|vpn_enabled|$setup_vpn|g" "$env_file" || \
log_error "Failed to update .env file"
This steps prepares all the files with the correct information that was collected on the "[[#gather-all-the-required-information][Gather all the
required information]]" step.
#+begin_src bash
sed -i -e "s|<your_PUID>|$puid|g" "$env_file" \
-e "s|<your_PGID>|$pgid|g" "$env_file" \
-e "s|<media_directory>|$media_directory|g" "$env_file" \
-e "s|<media_service>|$media_service|g" "$env_file" \
-e "s|<media_service>|$media_service|g" "$filename"
# Update docker-compose.yaml
log_info "Updating docker-compose configuration..."
sed -i "s|<media_service>|$media_service|g" "$filename" || \
log_error "Failed to update docker-compose.yaml"
# Configure Plex-specific settings
if [ "$media_service" == "plex" ]; then
sed -i -e "s|#network_mode: host # plex|network_mode: host # plex|g" "$filename" \
-e "s|ports: # plex|#ports: # plex|g" "$filename" \
-e "s|- 8096:8096 # plex|#- 8096:8096 # plex|g" "$filename"
log_info "Configuring Plex-specific settings..."
sed -i -e 's|#network_mode: host # plex|network_mode: host # plex|g' \
-e 's|ports: # plex|#ports: # plex|g' \
-e 's|- 8096:8096 # plex|#- 8096:8096 # plex|g' "$filename" || \
log_error "Failed to configure Plex settings"
fi
sed -i -e "s|<install_directory>|$install_directory|g" "$env_file" \
-e "s|vpn_enabled|$setup_vpn|g" "$env_file" \
if [ "$setup_vpn" == "y" ]; then
sed -i -e "s|vpn_service|$vpn_service|g" "$env_file" \
-e "s|vpn_user|$vpn_user|g" "$env_file" \
-e "s|vpn_password|$vpn_password|g" "$env_file" \
-e "s|#network_mode: \"service:gluetun\"|network_mode: \"service:gluetun\"|g" "$filename" \
-e "s|ports: # qbittorrent|#ports: # qbittorrent|g" "$filename" \
-e "s|ports: # sabnzbd|#ports: # sabnzbd|g" "$filename" \
-e "s|- 8081:8081 # qbittorrent|#- 8081:8081 # qbittorrent|g" "$filename" \
-e "s|- 8080:8080 # sabnzbd|#- 8080:8080 # sabnzbd|g" "$filename" \
-e "s|#- 8080:8080/tcp # gluetun|- 8080:8080/tcp # gluetun|g" "$filename"
-e "s|#- 8081:8081/tcp # gluetun|- 8081:8081/tcp # gluetun|g" "$filename"
# Configure VPN settings if enabled
if [ "${setup_vpn,,}" == "y" ]; then
log_info "Configuring VPN settings..."
sed -i -e "s|vpn_service|$vpn_service|g" \
-e "s|vpn_user|$vpn_user|g" \
-e "s|vpn_password|$vpn_password|g" \
-e 's|#network_mode: "service:gluetun"|network_mode: "service:gluetun"|g' \
-e 's|ports: # qbittorrent|#ports: # qbittorrent|g' \
-e 's|ports: # sabnzbd|#ports: # sabnzbd|g' \
-e 's|- 8081:8081 # qbittorrent|#- 8081:8081 # qbittorrent|g' \
-e 's|- 8080:8080 # sabnzbd|#- 8080:8080 # sabnzbd|g' \
-e 's|#- 8080:8080/tcp # gluetun|- 8080:8080/tcp # gluetun|g' \
-e 's|#- 8081:8081/tcp # gluetun|- 8081:8081/tcp # gluetun|g' "$filename" || \
log_error "Failed to configure VPN settings"
fi
#+end_src
** Set the configuration for the YAMS binary
:PROPERTIES:
:ID: b6a8732f-9dbe-4d93-b04d-27156eacdea2
:END:
#+begin_src bash
sed -i -e "s|<filename>|$filename|g" yams \
-e "s|<custom_file_filename>|$custom_file_filename|g" yams \
-e "s|<install_directory>|$install_directory|g" yams
#+end_src
** Success message!
:PROPERTIES:
:ID: 7b0ed8f5-780b-4685-8123-8d5c4229eaba
:END:
Finally, YAMS is installed 🔥. Show the success message
#+begin_src bash
send_success_message "Everything installed correctly! 🎉"
echo "Running the server..."
echo "This is going to take a while..."
docker compose -f "$filename" up -d
#+end_src
* Final steps
:PROPERTIES:
:ID: 65ce5828-b69a-4a0e-83f6-b029e19caea1
:END:
** Install the YAMS CLI
:PROPERTIES:
:ID: f4f9d166-8a2b-4d79-bc7f-fe73ecf5fb77
:END:
This steps requires ~sudo~ because it's copying the main yams script to the ~/usr/local/bin/yams~
directory.
#+begin_src bash
echo -e "\nWe need your sudo password to install the YAMS CLI and configure permissions..."
# Update YAMS CLI script
log_info "Updating YAMS CLI configuration..."
sed -i -e "s|<filename>|$filename|g" \
-e "s|<custom_file_filename>|$install_directory/docker-compose.custom.yaml|g" \
-e "s|<install_directory>|$install_directory|g" "$yams_script" || \
log_error "Failed to update YAMS CLI script"
}
install_cli() {
log_info "\nInstalling YAMS CLI..."
if sudo cp yams /usr/local/bin/yams && sudo chmod +x /usr/local/bin/yams; then
send_success_message "YAMS CLI installed successfully ✅"
log_success "YAMS CLI installed successfully ✅"
else
send_error_message "Failed to install YAMS CLI. Make sure you have the necessary permissions ❌"
log_error "Failed to install YAMS CLI. Check permissions ❌"
fi
}
set_permissions() {
local dirs=("$media_directory" "$install_directory" "$install_directory/config")
for dir in "${dirs[@]}"; do
log_info "Setting permissions for $dir..."
if [ ! -d "$dir" ]; then
mkdir -p "$dir" || log_error "Failed to create directory $dir"
fi
if sudo chown -R "$puid:$pgid" "$dir"; then
log_success "Permissions set successfully for $dir ✅"
else
log_error "Failed to set permissions for $dir ❌"
fi
done
}
#+end_src
** Set the correct permissions to the media and install directories
* Script Execution
:PROPERTIES:
:ID: 4cfb9397-776d-46db-84cc-54b78395cba8
:ID: new-script-execution
:END:
This adds the correct permissions to the media folder, in case they are not correct.
#+begin_src bash
if sudo chown -R "$puid":"$pgid" "$media_directory"; then
send_success_message "Media directory ownership and permissions set successfully ✅"
else
send_error_message "Failed to set ownership and permissions for the media directory. Check permissions ❌"
fi
if sudo chown -R "$puid":"$pgid" "$install_directory"; then
send_success_message "Install directory ownership and permissions set successfully ✅"
else
send_error_message "Failed to set ownership and permissions for the install directory. Check permissions ❌"
fi
#+end_src
** Create the config directory
** Verify Prerequisites
:PROPERTIES:
:ID: 699f35fe-edde-406d-be0b-3ff2eaa6d7eb
:ID: e945d5a8-5142-41fe-8175-96de7aa84cf2
:END:
This is where all the configurations are going to be saved. If it doesn't it will try and create it. If
it can't be created, we'll raise an error.
#+begin_src bash
if [[ -d "$install_directory/config" ]]; then
send_success_message "Configuration folder \"$install_directory/config\" exists ✅"
else
if sudo mkdir -p "$install_directory/config"; then
send_success_message "Configuration folder \"$install_directory/config\" created ✅"
else
send_error_message "Failed to create or access the configuration folder. Check permissions ❌"
fi
# Prevent running as root
if [[ "$EUID" = 0 ]]; then
log_error "YAMS must run without sudo! Please run with regular permissions"
fi
if sudo chown -R "$puid":"$pgid" "$install_directory/config"; then
send_success_message "Configuration folder ownership and permissions set successfully ✅"
else
send_error_message "Failed to set ownership and permissions for the configuration folder. Check permissions ❌"
fi
# Check all dependencies
log_info "Checking prerequisites..."
check_dependencies
#+end_src
* Display closing message
** Installation Process
:PROPERTIES:
:ID: new-installation-process
:END:
#+begin_src bash
# Get user information
get_user_info
# Get installation paths
get_installation_paths
# Configure services
configure_media_service
configure_vpn
log_info "Configuring the docker-compose file for user \"$username\" in \"$install_directory\"..."
# Copy and update configuration files
copy_configuration_files
update_configuration_files
log_success "Everything installed correctly! 🎉"
# Start services
log_info "Starting YAMS services..."
log_info "This may take a while..."
if ! docker compose -f "$install_directory/docker-compose.yaml" up -d; then
log_error "Failed to start YAMS services"
fi
# Install CLI and set permissions
log_info "\nWe need your sudo password to install the YAMS CLI and configure permissions..."
install_cli
set_permissions
#+end_src
* Display Closing Message
:PROPERTIES:
:ID: 238e3eae-9df7-4a7f-a460-7a61c07b5442
:END:
@ -517,36 +505,42 @@ fi
#+begin_src bash
printf "\033c"
echo "========================================================"
echo " _____ ___ ___ ___ "
echo " / /::\ / /\ /__/\ / /\ "
echo " / /:/\:\ / /::\ \ \:\ / /:/_ "
echo " / /:/ \:\ / /:/\:\ \ \:\ / /:/ /\ "
echo " /__/:/ \__\:| / /:/ \:\ _____\__\:\ / /:/ /:/_ "
echo " \ \:\ / /:/ /__/:/ \__\:\ /__/::::::::\ /__/:/ /:/ /\\"
echo " \ \:\ /:/ \ \:\ / /:/ \ \:\~~\~~\/ \ \:\/:/ /:/"
echo " \ \:\/:/ \ \:\ /:/ \ \:\ ~~~ \ \::/ /:/ "
echo " \ \::/ \ \:\/:/ \ \:\ \ \:\/:/ "
echo " \__\/ \ \::/ \ \:\ \ \::/ "
echo " \__\/ \__\/ \__\/ "
echo "========================================================"
send_success_message "All done!✅ Enjoy YAMS!"
echo "You can check the installation on $install_directory"
echo "========================================================"
echo "Everything should be running now! To check everything running, go to:"
cat << "EOF"
========================================================
_____ ___ ___ ___
/ /::\ / /\ /__/\ / /\
/ /:/\:\ / /::\ \ \:\ / /:/_
/ /:/ \:\ / /:/\:\ \ \:\ / /:/ /\
/__/:/ \__\:| / /:/ \:\ _____\__\:\ / /:/ /:/_
\ \:\ / /:/ /__/:/ \__\:\ /__/::::::::\ /__/:/ /:/ /\\
\ \:\ /:/ \ \:\ / /:/ \ \:\~~\~~\/ \ \:\/:/ /:/
\ \:\/:/ \ \:\ /:/ \ \:\ ~~~ \ \::/ /:/
\ \::/ \ \:\/:/ \ \:\ \ \:\/:/
\__\/ \ \::/ \ \:\ \ \::/
\__\/ \__\/ \__\/
========================================================
EOF
log_success "All done!✅ Enjoy YAMS!"
log_info "You can check the installation in $install_directory"
log_info "========================================================"
log_info "Everything should be running now! To check everything running, go to:"
echo
running_services_location
echo
log_info "You might need to wait for a couple of minutes while everything gets up and running"
echo
echo "You might need to wait for a couple of minutes while everything gets up and running"
echo
echo "All the services location are also saved in ~/yams_services.txt"
log_info "All the service locations are also saved in ~/yams_services.txt"
running_services_location > ~/yams_services.txt
echo "========================================================"
log_info "========================================================"
echo
echo "To configure YAMS, check the documentation at"
echo "https://yams.media/config"
log_info "To configure YAMS, check the documentation at"
log_info "https://yams.media/config"
echo
echo "========================================================"
log_info "========================================================"
exit 0
#+end_src

View File

@ -23,172 +23,165 @@ echo "To finish the installation of the CLI"
echo "===================================================="
echo ""
send_success_message() {
echo -e $(printf "\e[32m$1\e[0m")
# Constants
readonly DEFAULT_INSTALL_DIR="/opt/yams"
readonly DEFAULT_MEDIA_DIR="/srv/media"
readonly SUPPORTED_MEDIA_SERVICES=("jellyfin" "emby" "plex")
readonly DEFAULT_MEDIA_SERVICE="jellyfin"
readonly DEFAULT_VPN_SERVICE="protonvpn"
readonly MEDIA_SUBDIRS=("tv" "movies" "music" "books" "downloads" "blackhole")
# Color codes
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly NC='\033[0m' # No Color
# Dependencies
readonly REQUIRED_COMMANDS=("curl" "docker" "docker" "sed" "awk")
log_success() {
echo -e "${GREEN}$1${NC}"
}
send_error_message() {
echo -e $(printf "\e[31m$1\e[0m")
exit 255
log_error() {
echo -e "${RED}$1${NC}" >&2
exit 1
}
check_dependencies() {
if command -v docker &> /dev/null; then
send_success_message "docker exists ✅ "
if docker compose version &> /dev/null; then
send_success_message "docker compose exists ✅ "
else
echo -e $(printf "\e[31m ⚠️ docker compose not found! ⚠️\e[0m")
read -p "Do you want YAMS to install Docker Compose? IT ONLY WORKS ON DEBIAN AND UBUNTU! (y/N) [Default = n]: " install_docker
install_docker=${install_docker:-"n"}
log_warning() {
echo -e "${YELLOW}$1${NC}"
}
if [ "$install_docker" == "y" ]; then
bash ./docker.sh
else
send_error_message "Install Docker Compose and come back later!"
fi
fi
else
echo -e $(printf "\e[31m ⚠️ docker not found! ⚠️\e[0m")
read -p "Do you want YAMS to install Docker and Docker Compose? IT ONLY WORKS ON DEBIAN AND UBUNTU! (y/N) [Default = n]: " install_docker
install_docker=${install_docker:-"n"}
log_info() {
echo "$1"
}
if [ "$install_docker" == "y" ]; then
bash ./docker.sh
create_and_verify_directory() {
local dir="$1"
local dir_type="$2"
if [ ! -d "$dir" ]; then
echo "The directory \"$dir\" does not exist. Attempting to create..."
if mkdir -p "$dir"; then
log_success "Directory $dir created ✅"
else
send_error_message "Install Docker and Docker Compose and come back later!"
log_error "Failed to create $dir_type directory at \"$dir\". Check permissions ❌"
fi
fi
if [ ! -w "$dir" ] || [ ! -r "$dir" ]; then
log_error "Directory \"$dir\" is not writable or readable. Check permissions ❌"
fi
}
running_services_location() {
host_ip=$(hostname -I | awk '{ print $1 }')
setup_directory_structure() {
local media_dir="$1"
services=(
"qBittorrent:8081"
"SABnzbd:8080"
"Radarr:7878"
"Sonarr:8989"
"Lidarr:8686"
"Readarr:8787"
"Prowlarr:9696"
"Bazarr:6767"
"$media_service:$media_service_port"
"Portainer:9000"
)
create_and_verify_directory "$media_dir" "media"
echo -e "Service URLs:"
for service in "${services[@]}"; do
service_name="${service%%:*}"
service_port="${service##*:}"
echo "$service_name: http://$host_ip:$service_port/"
for subdir in "${MEDIA_SUBDIRS[@]}"; do
create_and_verify_directory "$media_dir/$subdir" "media subdirectory"
done
}
echo "Checking prerequisites..."
verify_user_permissions() {
local username="$1"
local directory="$2"
check_dependencies
if [[ "$EUID" = 0 ]]; then
send_error_message "YAMS has to run without sudo! Please, run it again with regular permissions"
if ! id -u "$username" &>/dev/null; then
log_error "User \"$username\" doesn't exist!"
fi
default_install_directory="/opt/yams"
if ! sudo -u "$username" test -w "$directory"; then
log_error "User \"$username\" doesn't have write permissions to \"$directory\""
fi
}
read -p "Where do you want to install the docker-compose file? [$default_install_directory]: " install_directory
install_directory=${install_directory:-$default_install_directory}
check_dependencies() {
# Check for required commands
for cmd in "${REQUIRED_COMMANDS[@]}"; do
if ! command -v "$cmd" &> /dev/null; then
log_error "Required command '$cmd' not found!"
fi
done
if [ ! -d "$install_directory" ]; then
echo "The directory \"$install_directory\" does not exists. Attempting to create..."
if mkdir -p "$install_directory"; then
send_success_message "Directory $install_directory created ✅"
# Check Docker
if command -v docker &> /dev/null; then
log_success "docker exists ✅"
if docker compose version &> /dev/null; then
log_success "docker compose exists ✅"
return 0
fi
fi
log_warning "⚠️ Docker/Docker Compose not found! ⚠️"
read -p "Install Docker and Docker Compose? Only works on Debian/Ubuntu (y/N) [Default = n]: " install_docker
install_docker=${install_docker:-"n"}
if [ "${install_docker,,}" = "y" ]; then
bash ./docker.sh
else
send_error_message "There was an error creating the installation directory at \"$install_directory\". Make sure you have the necessary permissions ❌"
fi
log_error "Please install Docker and Docker Compose first"
fi
}
if [ ! -w "$install_directory" ] || [ ! -r "$install_directory" ]; then
send_error_message "The directory \"$install_directory\" is not writable or readable by the current user. Set the correct permissions or try a different directory"
fi
configure_media_service() {
log_info "\nTime to choose your media service."
log_info "Your media service is responsible for serving your files to your network."
log_info "Supported media services:"
log_info "- jellyfin (recommended, easier)"
log_info "- emby"
log_info "- plex (advanced, always online)"
filename="$install_directory/docker-compose.yaml"
custom_file_filename="$install_directory/docker-compose.custom.yaml"
env_file="$install_directory/.env"
read -p "What's the user that is going to own the media server files? [$USER]: " username
username=${username:-$USER}
if id -u "$username" &>/dev/null; then
puid=$(id -u "$username");
pgid=$(id -g "$username");
else
send_error_message "The user \"$username\" doesn't exist!"
fi
read -p "Please, input your media directory [/srv/media]: " media_directory
media_directory=${media_directory:-"/srv/media"}
read -p "Are you sure your media directory is \"$media_directory\"? (y/N) [Default = n]: " media_directory_correct
media_directory_correct=${media_directory_correct:-"n"}
if [ ! -d "$media_directory" ]; then
echo "The directory \"$media_directory\" does not exists. Attempting to create..."
if mkdir -p "$media_directory"; then
send_success_message "Directory $media_directory created ✅"
else
send_error_message "There was an error creating the installation directory at \"$media_directory\". Make sure you have the necessary permissions ❌"
fi
fi
if [ "$media_directory_correct" == "n" ]; then
send_error_message "Media directory is not correct. Please fix it and run the script again ❌"
fi
echo -e "\n\n\nTime to choose your media service."
echo "Your media service is responsible for serving your files to your network."
echo "By default, YAMS supports 3 media services:"
echo "- jellyfin (recommended, easier)"
echo "- emby"
echo "- plex (advanced, always online)"
read -p "Choose your media service [jellyfin]: " media_service
media_service=${media_service:-"jellyfin"}
read -p "Choose your media service [$DEFAULT_MEDIA_SERVICE]: " media_service
media_service=${media_service:-$DEFAULT_MEDIA_SERVICE}
media_service=$(echo "$media_service" | awk '{print tolower($0)}')
media_service_port=8096
if [[ ! " ${SUPPORTED_MEDIA_SERVICES[@]} " =~ " ${media_service} " ]]; then
log_error "\"$media_service\" is not supported by YAMS"
fi
# Set media service port
if [ "$media_service" == "plex" ]; then
media_service_port=32400
fi
if echo "emby plex jellyfin" | grep -qw "$media_service"; then
echo -e "\nYAMS is going to install \"$media_service\" on port \"$media_service_port\""
else
send_error_message "\"$media_service\" is not supported by YAMS. Are you sure you chose the correct service?"
media_service_port=8096
fi
echo -e "\nTime to set up the VPN."
echo "You can check the supported VPN list here: https://yams.media/advanced/vpn."
log_success "\nYAMS will install \"$media_service\" on port \"$media_service_port\""
read -p "Do you want to configure a VPN? (Y/n) [Default = y]: " setup_vpn
# Export for use in other functions
export media_service media_service_port
}
configure_vpn() {
log_info "\nTime to set up the VPN."
log_info "Supported VPN providers: https://yams.media/advanced/vpn"
read -p "Configure VPN? (Y/n) [Default = y]: " setup_vpn
setup_vpn=${setup_vpn:-"y"}
if [ "$setup_vpn" == "y" ]; then
read -p "What's your VPN service? (with spaces) [protonvpn]: " vpn_service
vpn_service=${vpn_service:-"protonvpn"}
if [ "${setup_vpn,,}" != "y" ]; then
export setup_vpn="n"
return 0
fi
echo -e "\nYou should read $vpn_service's documentation in case it has different configurations for username and password."
echo "The documentation for $vpn_service is here: https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/${vpn_service// /-}.md"
read -p "VPN service? (with spaces) [$DEFAULT_VPN_SERVICE]: " vpn_service
vpn_service=${vpn_service:-$DEFAULT_VPN_SERVICE}
read -p "What's your VPN username? (without spaces): " vpn_user
log_info "\nPlease check $vpn_service's documentation for specific configuration:"
log_info "https://github.com/qdm12/gluetun-wiki/blob/main/setup/providers/${vpn_service// /-}.md"
read -p "VPN username (without spaces): " vpn_user
[ -z "$vpn_user" ] && log_error "VPN username cannot be empty"
# Use hidden input for password
unset vpn_password
charcount=0
prompt="What's your VPN password? (if you are using mullvad, just enter your username again): "
while IFS= read -p "$prompt" -r -s -n 1 char
do
if [[ $char == $'\0' ]]
then
prompt="VPN password (if using mullvad, enter username again): "
while IFS= read -p "$prompt" -r -s -n 1 char; do
if [[ $char == $'\0' ]]; then
break
fi
if [[ $char == $'\177' ]]; then
@ -206,134 +199,246 @@ if [ "$setup_vpn" == "y" ]; then
fi
done
echo
fi
echo "Configuring the docker-compose file for the user \"$username\" on \"$install_directory\"..."
[ -z "$vpn_password" ] && log_error "VPN password cannot be empty"
copy_files=(
"docker-compose.example.yaml:$filename"
".env.example:$env_file"
"docker-compose.custom.yaml:$custom_file_filename"
# Export for use in other functions
export vpn_service vpn_user vpn_password setup_vpn
}
running_services_location() {
local host_ip
host_ip=$(hostname -I | awk '{ print $1 }')
local -A services=(
["qBittorrent"]="8081"
["SABnzbd"]="8080"
["Radarr"]="7878"
["Sonarr"]="8989"
["Lidarr"]="8686"
["Readarr"]="8787"
["Prowlarr"]="9696"
["Bazarr"]="6767"
["$media_service"]="$media_service_port"
["Portainer"]="9000"
)
for file_mapping in "${copy_files[@]}"; do
source_file="${file_mapping%%:*}"
destination_file="${file_mapping##*:}"
echo -e "Service URLs:"
for service in "${!services[@]}"; do
echo "$service: http://$host_ip:${services[$service]}/"
done
}
echo -e "\nCopying $source_file to $destination_file..."
if cp "$source_file" "$destination_file"; then
send_success_message "$source_file was copied successfuly! ✅"
get_user_info() {
read -p "User to own the media server files? [$USER]: " username
username=${username:-$USER}
if id -u "$username" &>/dev/null; then
puid=$(id -u "$username")
pgid=$(id -g "$username")
else
send_error_message "Failed to copy $source_file to $destination_file. Ensure your user ($USER) has the necessary permissions ❌"
log_error "User \"$username\" doesn't exist!"
fi
export username puid pgid
}
get_installation_paths() {
read -p "Installation directory? [$DEFAULT_INSTALL_DIR]: " install_directory
install_directory=${install_directory:-$DEFAULT_INSTALL_DIR}
create_and_verify_directory "$install_directory" "installation"
read -p "Media directory? [$DEFAULT_MEDIA_DIR]: " media_directory
media_directory=${media_directory:-$DEFAULT_MEDIA_DIR}
read -p "Are you sure your media directory is \"$media_directory\"? (y/N) [Default = n]: " media_directory_correct
media_directory_correct=${media_directory_correct:-"n"}
if [ "${media_directory_correct,,}" != "y" ]; then
log_error "Media directory is not correct. Please fix it and run the script again ❌"
fi
setup_directory_structure "$media_directory"
verify_user_permissions "$username" "$media_directory"
export install_directory media_directory
}
copy_configuration_files() {
local -A files=(
["docker-compose.example.yaml"]="docker-compose.yaml"
[".env.example"]=".env"
["docker-compose.custom.yaml"]="docker-compose.custom.yaml"
)
for src in "${!files[@]}"; do
local dest="$install_directory/${files[$src]}"
log_info "\nCopying $src to $dest..."
if cp "$src" "$dest"; then
log_success "$src copied successfully ✅"
else
log_error "Failed to copy $src to $dest. Check permissions ❌"
fi
done
}
sed -i -e "s|<your_PUID>|$puid|g" "$env_file" \
-e "s|<your_PGID>|$pgid|g" "$env_file" \
-e "s|<media_directory>|$media_directory|g" "$env_file" \
-e "s|<media_service>|$media_service|g" "$env_file" \
-e "s|<media_service>|$media_service|g" "$filename"
update_configuration_files() {
local filename="$install_directory/docker-compose.yaml"
local env_file="$install_directory/.env"
local yams_script="yams"
# Update .env file
log_info "Updating environment configuration..."
sed -i -e "s|<your_PUID>|$puid|g" \
-e "s|<your_PGID>|$pgid|g" \
-e "s|<media_directory>|$media_directory|g" \
-e "s|<media_service>|$media_service|g" \
-e "s|<install_directory>|$install_directory|g" \
-e "s|vpn_enabled|$setup_vpn|g" "$env_file" || \
log_error "Failed to update .env file"
# Update docker-compose.yaml
log_info "Updating docker-compose configuration..."
sed -i "s|<media_service>|$media_service|g" "$filename" || \
log_error "Failed to update docker-compose.yaml"
# Configure Plex-specific settings
if [ "$media_service" == "plex" ]; then
sed -i -e "s|#network_mode: host # plex|network_mode: host # plex|g" "$filename" \
-e "s|ports: # plex|#ports: # plex|g" "$filename" \
-e "s|- 8096:8096 # plex|#- 8096:8096 # plex|g" "$filename"
log_info "Configuring Plex-specific settings..."
sed -i -e 's|#network_mode: host # plex|network_mode: host # plex|g' \
-e 's|ports: # plex|#ports: # plex|g' \
-e 's|- 8096:8096 # plex|#- 8096:8096 # plex|g' "$filename" || \
log_error "Failed to configure Plex settings"
fi
sed -i -e "s|<install_directory>|$install_directory|g" "$env_file" \
-e "s|vpn_enabled|$setup_vpn|g" "$env_file" \
if [ "$setup_vpn" == "y" ]; then
sed -i -e "s|vpn_service|$vpn_service|g" "$env_file" \
-e "s|vpn_user|$vpn_user|g" "$env_file" \
-e "s|vpn_password|$vpn_password|g" "$env_file" \
-e "s|#network_mode: \"service:gluetun\"|network_mode: \"service:gluetun\"|g" "$filename" \
-e "s|ports: # qbittorrent|#ports: # qbittorrent|g" "$filename" \
-e "s|ports: # sabnzbd|#ports: # sabnzbd|g" "$filename" \
-e "s|- 8081:8081 # qbittorrent|#- 8081:8081 # qbittorrent|g" "$filename" \
-e "s|- 8080:8080 # sabnzbd|#- 8080:8080 # sabnzbd|g" "$filename" \
-e "s|#- 8080:8080/tcp # gluetun|- 8080:8080/tcp # gluetun|g" "$filename" \
-e "s|#- 8081:8081/tcp # gluetun|- 8081:8081/tcp # gluetun|g" "$filename"
# Configure VPN settings if enabled
if [ "${setup_vpn,,}" == "y" ]; then
log_info "Configuring VPN settings..."
sed -i -e "s|vpn_service|$vpn_service|g" \
-e "s|vpn_user|$vpn_user|g" \
-e "s|vpn_password|$vpn_password|g" \
-e 's|#network_mode: "service:gluetun"|network_mode: "service:gluetun"|g' \
-e 's|ports: # qbittorrent|#ports: # qbittorrent|g' \
-e 's|ports: # sabnzbd|#ports: # sabnzbd|g' \
-e 's|- 8081:8081 # qbittorrent|#- 8081:8081 # qbittorrent|g' \
-e 's|- 8080:8080 # sabnzbd|#- 8080:8080 # sabnzbd|g' \
-e 's|#- 8080:8080/tcp # gluetun|- 8080:8080/tcp # gluetun|g' \
-e 's|#- 8081:8081/tcp # gluetun|- 8081:8081/tcp # gluetun|g' "$filename" || \
log_error "Failed to configure VPN settings"
fi
sed -i -e "s|<filename>|$filename|g" yams \
-e "s|<custom_file_filename>|$custom_file_filename|g" yams \
-e "s|<install_directory>|$install_directory|g" yams
send_success_message "Everything installed correctly! 🎉"
echo "Running the server..."
echo "This is going to take a while..."
docker compose -f "$filename" up -d
echo -e "\nWe need your sudo password to install the YAMS CLI and configure permissions..."
# Update YAMS CLI script
log_info "Updating YAMS CLI configuration..."
sed -i -e "s|<filename>|$filename|g" \
-e "s|<custom_file_filename>|$install_directory/docker-compose.custom.yaml|g" \
-e "s|<install_directory>|$install_directory|g" "$yams_script" || \
log_error "Failed to update YAMS CLI script"
}
install_cli() {
log_info "\nInstalling YAMS CLI..."
if sudo cp yams /usr/local/bin/yams && sudo chmod +x /usr/local/bin/yams; then
send_success_message "YAMS CLI installed successfully ✅"
log_success "YAMS CLI installed successfully ✅"
else
send_error_message "Failed to install YAMS CLI. Make sure you have the necessary permissions ❌"
log_error "Failed to install YAMS CLI. Check permissions ❌"
fi
}
set_permissions() {
local dirs=("$media_directory" "$install_directory" "$install_directory/config")
for dir in "${dirs[@]}"; do
log_info "Setting permissions for $dir..."
if [ ! -d "$dir" ]; then
mkdir -p "$dir" || log_error "Failed to create directory $dir"
fi
if sudo chown -R "$puid":"$pgid" "$media_directory"; then
send_success_message "Media directory ownership and permissions set successfully ✅"
if sudo chown -R "$puid:$pgid" "$dir"; then
log_success "Permissions set successfully for $dir"
else
send_error_message "Failed to set ownership and permissions for the media directory. Check permissions ❌"
log_error "Failed to set permissions for $dir"
fi
done
}
# Prevent running as root
if [[ "$EUID" = 0 ]]; then
log_error "YAMS must run without sudo! Please run with regular permissions"
fi
if sudo chown -R "$puid":"$pgid" "$install_directory"; then
send_success_message "Install directory ownership and permissions set successfully ✅"
else
send_error_message "Failed to set ownership and permissions for the install directory. Check permissions ❌"
# Check all dependencies
log_info "Checking prerequisites..."
check_dependencies
# Get user information
get_user_info
# Get installation paths
get_installation_paths
# Configure services
configure_media_service
configure_vpn
log_info "Configuring the docker-compose file for user \"$username\" in \"$install_directory\"..."
# Copy and update configuration files
copy_configuration_files
update_configuration_files
log_success "Everything installed correctly! 🎉"
# Start services
log_info "Starting YAMS services..."
log_info "This may take a while..."
if ! docker compose -f "$install_directory/docker-compose.yaml" up -d; then
log_error "Failed to start YAMS services"
fi
if [[ -d "$install_directory/config" ]]; then
send_success_message "Configuration folder \"$install_directory/config\" exists ✅"
else
if sudo mkdir -p "$install_directory/config"; then
send_success_message "Configuration folder \"$install_directory/config\" created ✅"
else
send_error_message "Failed to create or access the configuration folder. Check permissions ❌"
fi
fi
if sudo chown -R "$puid":"$pgid" "$install_directory/config"; then
send_success_message "Configuration folder ownership and permissions set successfully ✅"
else
send_error_message "Failed to set ownership and permissions for the configuration folder. Check permissions ❌"
fi
# Install CLI and set permissions
log_info "\nWe need your sudo password to install the YAMS CLI and configure permissions..."
install_cli
set_permissions
printf "\033c"
echo "========================================================"
echo " _____ ___ ___ ___ "
echo " / /::\ / /\ /__/\ / /\ "
echo " / /:/\:\ / /::\ \ \:\ / /:/_ "
echo " / /:/ \:\ / /:/\:\ \ \:\ / /:/ /\ "
echo " /__/:/ \__\:| / /:/ \:\ _____\__\:\ / /:/ /:/_ "
echo " \ \:\ / /:/ /__/:/ \__\:\ /__/::::::::\ /__/:/ /:/ /\\"
echo " \ \:\ /:/ \ \:\ / /:/ \ \:\~~\~~\/ \ \:\/:/ /:/"
echo " \ \:\/:/ \ \:\ /:/ \ \:\ ~~~ \ \::/ /:/ "
echo " \ \::/ \ \:\/:/ \ \:\ \ \:\/:/ "
echo " \__\/ \ \::/ \ \:\ \ \::/ "
echo " \__\/ \__\/ \__\/ "
echo "========================================================"
send_success_message "All done!✅ Enjoy YAMS!"
echo "You can check the installation on $install_directory"
echo "========================================================"
echo "Everything should be running now! To check everything running, go to:"
cat << "EOF"
========================================================
_____ ___ ___ ___
/ /::\ / /\ /__/\ / /\
/ /:/\:\ / /::\ \ \:\ / /:/_
/ /:/ \:\ / /:/\:\ \ \:\ / /:/ /\
/__/:/ \__\:| / /:/ \:\ _____\__\:\ / /:/ /:/_
\ \:\ / /:/ /__/:/ \__\:\ /__/::::::::\ /__/:/ /:/ /\\
\ \:\ /:/ \ \:\ / /:/ \ \:\~~\~~\/ \ \:\/:/ /:/
\ \:\/:/ \ \:\ /:/ \ \:\ ~~~ \ \::/ /:/
\ \::/ \ \:\/:/ \ \:\ \ \:\/:/
\__\/ \ \::/ \ \:\ \ \::/
\__\/ \__\/ \__\/
========================================================
EOF
log_success "All done!✅ Enjoy YAMS!"
log_info "You can check the installation in $install_directory"
log_info "========================================================"
log_info "Everything should be running now! To check everything running, go to:"
echo
running_services_location
echo
log_info "You might need to wait for a couple of minutes while everything gets up and running"
echo
echo "You might need to wait for a couple of minutes while everything gets up and running"
echo
echo "All the services location are also saved in ~/yams_services.txt"
log_info "All the service locations are also saved in ~/yams_services.txt"
running_services_location > ~/yams_services.txt
echo "========================================================"
log_info "========================================================"
echo
echo "To configure YAMS, check the documentation at"
echo "https://yams.media/config"
log_info "To configure YAMS, check the documentation at"
log_info "https://yams.media/config"
echo
echo "========================================================"
log_info "========================================================"
exit 0