cloudreve安装脚本,支持Fedora和Debian。
包含docker、docker compose、以及二进制文件安装方式。
包含 数据库设置、SSL设置。
docker compose安装方式采用Github Repo 内的docker-compose.yml文件

懒得测试,就这样吧

#!/bin/bash
# cloudreve.sh
# Copyright (c) [2026] [Konvict Liu / https://konvict.cn]
# 2026-02-07
# License:   Mozilla Public  License, v. 2.0
# 根据MPL 2.0的要求,对本文件的任何修改必须在文件开头明确说明。
# https://www.mozilla.org/en-US/MPL/2.0/

tarURL="https://github.com/cloudreve/cloudreve/releases/download/4.13.0/cloudreve_4.13.0_linux_amd64.tar.gz"
# shellcheck  disable=SC1091
source /etc/os-release

if [[ $(id -u) -ne 0 ]]; then
	echo "Please run as root"
	exit 1
fi

Color_Text() {
	echo -e " \e[0;$2m$1\e[0m"
}

Echo_Red() {
	echo $(Color_Text "$1" "31")
}

Echo_Green() {
	echo $(Color_Text "$1" "32")
}

Echo_Yellow() {
	echo $(Color_Text "$1" "33")
}

Echo_Blue() {
	echo $(Color_Text "$1" "34")
}
systemDistroVersion() {
	if [[ ${ID} == "debian" ]]; then
		Echo_Green "Debian detected"
		packageManager="apt"
	elif [[ ${ID} == "fedora" ]]; then
		Echo_Green "Fedora detected"
		packageManager="dnf"
	else
		Echo_Red "Unsupported OS"
		Echo_Red "This script only supports Fedora  and Debian."
		Echo_Red "Exiting"
		exit 1
	fi

	Echo_Blue "Detecting System Version..."

	if [[ ${ID} == "fedora" ]]; then
		Echo_Green "Fedora ${VERSION_ID} detected"
	elif [[ ${ID} == "debian" ]]; then
		Echo_Green "Debian ${VERSION_ID} detected"
	fi
}

installMethod() {
	echo "Please select the installation method:"
	echo "1. Install with systemd (Defalut)"
	echo "2. Install with Docker"
	echo "3. Install with Docker Compose"
	echo "4. Exit"
	read -rp "Enter your choice: " installMethod="${installMethod:-1}"
}

installDockerFedora() {
	dnf config-manager addrepo --from-repofile https://download.docker.com/linux/fedora/docker-ce.repo
	dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
	systemctl enable --now docker

}

installDockerDebian() {
	apt remove $(dpkg --get-selections docker.io docker-compose docker-doc podman-docker containerd runc | cut -f1)
	# Add Docker's official GPG key:
	apt update && apt install ca-certificates curl
	install -m 0755 -d /etc/apt/keyrings && curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
	chmod a+r /etc/apt/keyrings/docker.asc

	# Add the repository to Apt sources:
	tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(source /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF

	apt update && apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
	systemctl enable --now docker
}

installDocker() {
	if [[ $(command -v docker) ]]; then
		Echo_Green "Docker already installed"
	else
		Echo_Blue "Installing Docker..."
		if [[ ${ID} == "fedora" ]]; then
			installDockerFedora
		elif [[ ${ID} == "debian" ]]; then
			installDockerDebian
		fi
	fi
}

passwordWarning() {
	Echo_Yellow "Please input the database password."
	Echo_Yellow "The password must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter, one number, and one special character."
}

chooseDatabase() {
	echo "Please select a database:"
	echo "1. SQLite (default)"
	echo "2. MySQL"
	echo "3. PostgreSQL"
	echo "4. MariaDB"
	read -rp "Enter your choice: " dbChoice
	dbChoice=${dbChoice:-1}

	read -rp "Please enter the database host (default: localhost): " dbHost
	dbHost=${dbHost:-localhost}

	read -rp "Please enter the database port (default: 3306 for MySQL/MariaDB, 5432 for PostgreSQL): " dbPort
	if [[ -z "$dbPort" ]]; then
		if [[ $dbChoice -eq 2 ]]; then
			dbPort=3306
		elif [[ $dbChoice -eq 3 ]]; then
			dbPort=5432
		elif [[ $dbChoice -eq 4 ]]; then
			dbPort=3306
		fi
	fi

	read -rp "Please enter the database name (default: cloudreve): " dbName
	dbName=${dbName:-cloudreve}

	read -rp "Please enter the database username (default: root): " dbUser
	dbUser=${dbUser:-root}
	passwordWarning
	while true; do
		read -rp "Please enter the database password (default: empty): " dbPassword
		if [[ ${#dbPassword} -ge 8 && "$dbPassword" == *[[:lower:]]* && "$dbPassword" == *[[:upper:]]* && "$dbPassword" == *[0-9]* && "$dbPassword" == *[[:punct:]]* ]]; then
			break
		else
			Echo_Red "The password is not strong enough."
			Echo_Red "Please try again."
		fi
	done

	echo "Database configurations: "
	echo "Type: $([[ $dbChoice -eq 1 ]] && echo 'SQLite' || ([[ $dbChoice -eq 2 ]] && echo 'MySQL' || ([[ $dbChoice -eq 4 ]] && echo 'MariaDB' || echo 'PostgreSQL')))"
	echo "Host: $dbHost"
	echo "Port: $dbPort"
	echo "Name: $dbName"
	echo "User: $dbUser"
	echo "Password: $dbPassword"
}
configDBDocker() {
	case $dbChoice in
	1)
		dbConfig=""
		;;
	2)
		dbConfig="-e CR_CONF_Database.Type=mysql -e CR_CONF_Database.Host=$dbHost -e CR_CONF_Database.Port=$dbPort -e CR_CONF_Database.Name=$dbName -e CR_CONF_Database.User=$dbUser -e CR_CONF_Database.Password=$dbPassword"
		;;
	3)
		# shellcheck disable=SC2034
		dbConfig="-e CR_CONF_Database.Type=postgresql -e CR_CONF_Database.Host=$dbHost -e CR_CONF_Database.Port=$dbPort -e CR_CONF_Database.Name=$dbName -e CR_CONF_Database.User=$dbUser -e CR_CONF_Database.Password=$dbPassword"
		;;
	4)
		dbConfig="-e CR_CONF_Database.Type=mariadb -e CR_CONF_Database.Host=$dbHost -e CR_CONF_Database.Port=$dbPort -e CR_CONF_Database.Name=$dbName -e CR_CONF_Database.User=$dbUser -e CR_CONF_Database.Password=$dbPassword"
		;;
	*)
		Echo_Red "Invalid database choice"
		exit 1
		;;
	esac
}

installCloudreveDocker() {
	read -r -p "please input the port you want to use for cloudreve (default: 5212): " port
	port=${port:-5212}
	read -r -p "please input the path you want to use for cloudreve (default: ~/cloudreve): " cloudreveDataDir
	cloudreveDataDir=${cloudreveDataDir:-${installDir}/data}
	mkdir -p "${cloudreveDataDir}"
	docker run -dit --name cloudreve \
		--restart=unless-stopped \
		-p "${port}":5212 \
		-v "${cloudreveDataDir}":/cloudreve/data \
		"${dbConfig}" \
		cloudreve/cloudreve:latest
	Echo_Green "Cloudreve installed successfully"
	Echo_Green "Cloudreve is running at: "
	for i in $(hostname -I); do echo "http://$i:${port}"; done
	unset port cloudreveDataDir i
}

installCloudreveDockerCompose() {
	Echo_Yellow "Installing Cloudreve with Docker Compose..."
	Echo_Yellow "Database file using PostgreSQL"
	Echo_Yellow "Other services: Redis"

	read -r -p "please input the port you want to use for cloudreve (default: 5212): " port
	port=${port:-5212}
	mkdir -p "${cloudreveDataDir}"
	cat >docker-compose.yml <<EOF
services:
  cloudreve:
    image: cloudreve/cloudreve:latest
    container_name: cloudreve-backend
    depends_on:
      - postgresql
      - redis
    restart: unless-stopped
    ports:
      - ${port}:5212
    environment:
      - CR_CONF_Database.Type=postgres
      - CR_CONF_Database.Host=postgresql
      - CR_CONF_Database.User=cloudreve
      - CR_CONF_Database.Name=cloudreve
      - CR_CONF_Database.Port=5432
      - CR_CONF_Redis.Server=redis:6379
    volumes:
      - backend_data:/cloudreve/data

  postgresql:
    # Best practice: Pin to major version. 
    # NOTE: For major version jumps:
    # backup & consult https://www.postgresql.org/docs/current/pgupgrade.html 
    image: postgres:17    
    container_name: postgresql
    restart: unless-stopped
    environment:
      - POSTGRES_USER=cloudreve
      - POSTGRES_DB=cloudreve
      - POSTGRES_HOST_AUTH_METHOD=trust
    volumes:
      - database_postgres:/var/lib/postgresql/data

  redis:
    image: redis:latest
    container_name: redis
    restart: unless-stopped
    volumes:
      - redis_data:/data

volumes:
  backend_data:
  database_postgres:
  redis_data:
EOF
	if docker compose up -d; then
		Echo_Green "Cloudreve installed successfully"
		Echo_Green "Cloudreve is running at: "
		for i in $(hostname -I); do echo "http://$i:${port}"; done
		unset port cloudreveDataDir i
	else
		Echo_Red "Failed to start cloudreve"
		exit 1
	fi

}

chooseInstallDir() {
	read -r -p "Please input the installation directory for cloudreve (default: /opt/cloudreve): " installDir
	installDir=${installDir:-/opt/cloudreve}
}

# Download and extract the tarball
installCloudreveBinary() {
	wget ${tarURL}

	if [[ -d ${installDir} ]]; then
		:
	else
		mkdir -p "${installDir}"
		tar -xzf cloudreve_4.13.0_linux_amd64.tar.gz -C "${installDir}"
	fi
}

configFilePath() {
	read -r -p "please input the path you want to use for cloudreve (default: ~/cloudreve): " cloudreveDataDir
	cloudreveDataDir=${cloudreveDataDir:-${installDir}/data}
	read -r -p "Please input the path you want to use for cloudreve (Full path with file name. Default: ${cloudreveDataDir}/config.ini): " cloudreveConfigFilePath
	cloudreveConfigFilePath=${cloudreveConfigFilePath:-${cloudreveDataDir}/config.ini}
	# shellcheck disable=SC2034
	if [[ ${cloudreveConfigFilePath} == "${cloudreveDataDir}/config.ini" ]]; then
		cloudreveArgs=""
	else
		cloudreveArgs="-c ${cloudreveConfigFilePath} "
	fi
}
defaultConfigFile() {
	cat >"${cloudreveConfigFilePath}" <<EOF
[System]
Debug = false
Mode = master
Listen = :5212
SessionSecret = oOozI3MOb5JYXxuirRuoxgYU3hwZHk4oM5g1d44cGZ7jU2bMzKFmNAK11L8u9kWp
HashIDSalt = {HashIDSalt}
ProxyHeader = X-Forwarded-For
[UnixSocket]
Listen = /run/cloudreve/cloudreve.sock
Perm = 0666
EOF
}
configDBBinary() {
	if [[ $dbChoice -eq 1 ]]; then
		dbConfig=""
	elif [[ $dbChoice -eq 2 ]]; then # MySQL
		cat >>"${cloudreveConfigFilePath}" <<EOF
[Database]
Type = mysql
Host = ${dbHost}
Port = ${dbPort}
Name = ${dbName}
User = ${dbUser}
Password = ${dbPassword}
EOF
	elif [[ $dbChoice -eq 4 ]]; then # MariaDB
		cat >>"${cloudreveConfigFilePath}" <<EOF
[Database]
Type = mariadb
Host = ${dbHost}
Port = ${dbPort}
Name = ${dbName}
User = ${dbUser}
Password = ${dbPassword}
EOF
	else # PostgreSQL
		cat >>"${cloudreveConfigFilePath}" <<EOF
[Database]
Type = postgresql
Host = ${dbHost}
Port = ${dbPort}    
Name = ${dbName}
User = ${dbUser}
Password = ${dbPassword}
EOF
	fi
}

# Create systemd service
createSystemdService() {
	Echo_Yellow "Creating systemd service..."
	systemdFile="/etc/systemd/system/cloudreve.service"
	cat >"${systemdFile}" <<EOF
[Unit]
Description=Cloudreve
Documentation=https://docs.cloudreve.org
After=network.target
After=mysqld.service
Wants=network.target

[Service]
WorkingDirectory=${installDir}
ExecStart=${installDir}/cloudreve  ${cloudreveArgs}
Restart=on-abnormal
RestartSec=5s
KillMode=mixed

# 日志输出
StandardOutput=/var/log/cloudreve.log
StandardError=syslog

[Install]
WantedBy=multi-user.target
EOF
}

sslConfig() {
	read -r -p "Do you want to enable SSL? (y/N): " enableSSL
	enableSSL=${enableSSL:-N}
	if [[ $enableSSL == [Yy] ]]; then
		read -r -p "Please input the path to your SSL certificate file (default: /etc/ssl/certs/cloudreve.crt): " sslCertPath
		sslCertPath=${sslCertPath:-/etc/ssl/certs/cloudreve.crt}
		read -r -p "Please input the path to your SSL key file (default: /etc/ssl/private/cloudreve.key): " sslKeyPath
		sslKeyPath=${sslKeyPath:-/etc/ssl/private/cloudreve.key}
		read -r -p "please input the HTTPS port you want to use for cloudreve (default: 443): " httpsPort
		httpsPort=${httpsPort:-443}

		cat >>"${cloudreveConfigFilePath}" <<EOF
[SSL]
Listen = :${httpsPort}
CertPath = ${sslCertPath} ; 证书文件路径
KeyPath = ${sslKeyPath} ; 私钥文件路径
EOF
	fi
}
# Enable and start the service
enableAndStartService() {
	systemctl daemon-reload && systemctl enable --now cloudreve
}

systemDistroVersion
installMethod

if [[ ${installMethod} = 1 ]]; then
	chooseInstallDir
	installCloudreveBinary
	configFilePath
	defaultConfigFile
	chooseDatabase
	configDBBinary
	sslConfig
	createSystemdService
	enableAndStartService
elif [[ ${installMethod} = 2 ]]; then
	installDocker
	chooseDatabase
	configDBDocker
	installCloudreveDocker
elif [[ ${installMethod} = 3 ]]; then
	installDocker
	chooseDatabase
	installCloudreveDockerCompose
else
	Echo_Red "Invalid installation method"
	exit 1
fi