diff --git a/README.md b/README.md index c3412be14..14a741088 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Special thanks to our biggest sponsors! * [Latitude](https://latitude.sh/?ref=coolify.io) - A cloud computing platform offering bare metal servers and cloud instances for developers and businesses. * [Brand Dev](https://brand.dev/?ref=coolify.io) - A web development agency specializing in creating custom digital experiences and brand identities. * [Jobscollider](https://jobscollider.com/remote-jobs?ref=coolify.io) - A job search platform connecting professionals with remote work opportunities across various industries. -* [Hostinger](https://hostinger.com?ref=coolify.io) - A web hosting provider offering affordable hosting solutions, domain registration, and website building tools. +* [Hostinger](https://www.hostinger.com/vps/coolify-hosting?ref=coolify.io) - A web hosting provider offering affordable hosting solutions, domain registration, and website building tools. * [Glueops](https://www.glueops.dev/?ref=coolify.io) - A DevOps consulting company providing infrastructure automation and cloud optimization services. * [Ubicloud](https://ubicloud.com/?ref=coolify.io) - An open-source alternative to hyperscale cloud providers, offering high-performance cloud computing services. * [Juxtdigital](https://juxtdigital.dev/?ref=coolify.io) - A digital agency offering web development, design, and digital marketing services for businesses. diff --git a/app/Jobs/ServerCheckJob.php b/app/Jobs/ServerCheckJob.php index f7b54cd80..540085385 100644 --- a/app/Jobs/ServerCheckJob.php +++ b/app/Jobs/ServerCheckJob.php @@ -47,12 +47,12 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue public function middleware(): array { - return [(new WithoutOverlapping($this->server->uuid))]; + return [(new WithoutOverlapping($this->server->id))]; } public function uniqueId(): int { - return $this->server->uuid; + return $this->server->id; } public function handle() diff --git a/app/Livewire/Boarding/Index.php b/app/Livewire/Boarding/Index.php index 147a1ad6f..0bfcaf729 100644 --- a/app/Livewire/Boarding/Index.php +++ b/app/Livewire/Boarding/Index.php @@ -73,6 +73,8 @@ class Index extends Component } $this->privateKeyName = generate_random_name(); $this->remoteServerName = generate_random_name(); + $this->remoteServerPort = $this->remoteServerPort; + $this->remoteServerUser = $this->remoteServerUser; if (isDev()) { $this->privateKey = '-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW @@ -154,6 +156,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== $this->servers = Server::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get(); if ($this->servers->count() > 0) { $this->selectedExistingServer = $this->servers->first()->id; + $this->updateServerDetails(); $this->currentState = 'select-existing-server'; return; @@ -173,9 +176,18 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== } $this->selectedExistingPrivateKey = $this->createdServer->privateKey->id; $this->serverPublicKey = $this->createdServer->privateKey->publicKey(); + $this->updateServerDetails(); $this->currentState = 'validate-server'; } + private function updateServerDetails() + { + if ($this->createdServer) { + $this->remoteServerPort = $this->createdServer->port; + $this->remoteServerUser = $this->createdServer->user; + } + } + public function getProxyType() { // Set Default Proxy Type @@ -235,11 +247,12 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== public function saveServer() { $this->validate([ - 'remoteServerName' => 'required', - 'remoteServerHost' => 'required', + 'remoteServerName' => 'required|string', + 'remoteServerHost' => 'required|string', 'remoteServerPort' => 'required|integer', - 'remoteServerUser' => 'required', + 'remoteServerUser' => 'required|string', ]); + $this->privateKey = formatPrivateKey($this->privateKey); $foundServer = Server::whereIp($this->remoteServerHost)->first(); if ($foundServer) { @@ -277,9 +290,12 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== $this->createdServer->settings()->update([ 'is_reachable' => true, ]); + $this->serverReachable = true; } catch (\Throwable $e) { $this->serverReachable = false; - $this->createdServer->delete(); + $this->createdServer->settings()->update([ + 'is_reachable' => false, + ]); return handleError(error: $e, livewire: $this); } @@ -296,6 +312,10 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== ]); $this->getProxyType(); } catch (\Throwable $e) { + $this->createdServer->settings()->update([ + 'is_usable' => false, + ]); + return handleError(error: $e, livewire: $this); } } @@ -349,6 +369,21 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== ); } + public function saveAndValidateServer() + { + $this->validate([ + 'remoteServerPort' => 'required|integer|min:1|max:65535', + 'remoteServerUser' => 'required|string', + ]); + + $this->createdServer->update([ + 'port' => $this->remoteServerPort, + 'user' => $this->remoteServerUser, + 'timezone' => 'UTC', + ]); + $this->validateServer(); + } + private function createNewPrivateKey() { $this->privateKeyName = generate_random_name(); diff --git a/app/Models/Server.php b/app/Models/Server.php index c72c7cc95..46536ed47 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -112,6 +112,16 @@ class Server extends BaseModel 'proxy', ]; + protected $fillable = [ + 'name', + 'ip', + 'port', + 'user', + 'description', + 'private_key_id', + 'team_id', + ]; + protected $guarded = []; public static function isReachable() diff --git a/bootstrap/helpers/constants.php b/bootstrap/helpers/constants.php index f94c9bc20..1eeec8f94 100644 --- a/bootstrap/helpers/constants.php +++ b/bootstrap/helpers/constants.php @@ -46,6 +46,7 @@ const SUPPORTED_OS = [ 'centos fedora rhel ol rocky amzn almalinux', 'sles opensuse-leap opensuse-tumbleweed', 'arch', + 'alpine', ]; const SHARED_VARIABLE_TYPES = ['team', 'project', 'environment']; diff --git a/config/sentry.php b/config/sentry.php index a978caa5e..eb0a3a508 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.332', + 'release' => '4.0.0-beta.333', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/version.php b/config/version.php index cb4452172..c3c14e32b 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ /dev/null || true ;; +alpine) + sed -i '/^#.*\/community/s/^#//' /etc/apk/repositories + apk update >/dev/null + apk add curl wget git jq >/dev/null + ;; ubuntu | debian | raspbian) apt-get update -y >/dev/null apt-get install -y curl wget git jq >/dev/null @@ -172,70 +177,74 @@ if [ -x "$(command -v snap)" ]; then fi if ! [ -x "$(command -v docker)" ]; then - # Almalinux - if [ "$OS_TYPE" == 'almalinux' ]; then - dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo - dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin - if ! [ -x "$(command -v docker)" ]; then - echo "Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 - fi - systemctl start docker - systemctl enable docker - else - set +e - if ! [ -x "$(command -v docker)" ]; then - echo "Docker is not installed. Installing Docker." - # Arch Linux - if [ "$OS_TYPE" = "arch" ]; then - pacman -Sy docker docker-compose --noconfirm - systemctl enable docker.service + case "$OS_TYPE" in + "almalinux") + dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin + if ! [ -x "$(command -v docker)" ]; then + echo "Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker + systemctl enable docker + ;; + "alpine") + apk add docker docker-cli-compose + rc-update add docker default + service docker start + if [ -x "$(command -v docker)" ]; then + echo "Docker installed successfully." + else + echo "Failed to install Docker with apk. Try to install it manually." + echo "Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." + exit + fi + ;; + "arch") + pacman -Sy docker docker-compose --noconfirm + systemctl enable docker.service + if [ -x "$(command -v docker)" ]; then + echo "Docker installed successfully." + else + echo "Failed to install Docker with pacman. Try to install it manually." + echo "Please visit https://wiki.archlinux.org/title/docker for more information." + exit + fi + ;; + "amzn") + dnf install docker -y + DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} + mkdir -p $DOCKER_CONFIG/cli-plugins + curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose + chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose + systemctl start docker + systemctl enable docker + if [ -x "$(command -v docker)" ]; then + echo "Docker installed successfully." + else + echo "Failed to install Docker with dnf. Try to install it manually." + echo "Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." + exit + fi + ;; + *) + # Automated Docker installation + curl https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh + if [ -x "$(command -v docker)" ]; then + echo "Docker installed successfully." + else + echo "Docker installation failed with Rancher script. Trying with official script." + curl https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} if [ -x "$(command -v docker)" ]; then echo "Docker installed successfully." else - echo "Failed to install Docker with pacman. Try to install it manually." - echo "Please visit https://wiki.archlinux.org/title/docker for more information." - exit - fi - else - # Amazon Linux 2023 - if [ "$OS_TYPE" = "amzn" ]; then - dnf install docker -y - DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} - mkdir -p $DOCKER_CONFIG/cli-plugins - curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose - chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose - systemctl start docker - systemctl enable docker - if [ -x "$(command -v docker)" ]; then - echo "Docker installed successfully." - else - echo "Failed to install Docker with pacman. Try to install it manually." - echo "Please visit https://wiki.archlinux.org/title/docker for more information." - exit - fi - else - # Automated Docker installation - curl https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh - if [ -x "$(command -v docker)" ]; then - echo "Docker installed successfully." - else - echo "Docker installation failed with Rancher script. Trying with official script." - curl https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} - if [ -x "$(command -v docker)" ]; then - echo "Docker installed successfully." - else - echo "Docker installation failed with official script." - echo "Maybe your OS is not supported?" - echo "Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 - fi - fi + echo "Docker installation failed with official script." + echo "Maybe your OS is not supported?" + echo "Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 fi fi - fi - set -e - fi + esac fi echo -e "-------------" @@ -267,17 +276,50 @@ if ! jq -s '.[0] * .[1]' /etc/docker/daemon.json /etc/docker/daemon.json.coolify fi mv "$TEMP_FILE" /etc/docker/daemon.json +restart_docker_service() { + + # Check if systemctl is available + if command -v systemctl >/dev/null 2>&1; then + echo "Using systemctl to restart Docker..." + systemctl restart docker + + if [ $? -eq 0 ]; then + echo "Docker restarted successfully using systemctl." + else + echo "Failed to restart Docker using systemctl." + return 1 + fi + + # Check if service command is available + elif command -v service >/dev/null 2>&1; then + echo "Using service command to restart Docker..." + service docker restart + + if [ $? -eq 0 ]; then + echo "Docker restarted successfully using service." + else + echo "Failed to restart Docker using service." + return 1 + fi + + # If neither systemctl nor service is available + else + echo "Neither systemctl nor service command is available on this system." + return 1 + fi +} + if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE")) if [ "$DIFF" != "" ]; then echo "Docker configuration updated, restart docker daemon..." - systemctl restart docker + restart_docker_service else echo "Docker configuration is up to date." fi else echo "Docker configuration updated, restart docker daemon..." - systemctl restart docker + restart_docker_service fi echo -e "-------------" @@ -296,28 +338,35 @@ curl -fsSL $CDN/.env.production -o /data/coolify/source/.env.production curl -fsSL $CDN/upgrade.sh -o /data/coolify/source/upgrade.sh # Copy .env.example if .env does not exist -if [ ! -f $ENV_FILE ]; then - cp /data/coolify/source/.env.production $ENV_FILE - # Generate a secure APP_ID and APP_KEY - sed -i "s|^APP_ID=.*|APP_ID=$(openssl rand -hex 16)|" "$ENV_FILE" - sed -i "s|^APP_KEY=.*|APP_KEY=base64:$(openssl rand -base64 32)|" "$ENV_FILE" +if [ -f $ENV_FILE ]; then + echo "File exists: $ENV_FILE" + cat $ENV_FILE + echo "Copying .env to .env-$DATE" + cp $ENV_FILE $ENV_FILE-$DATE +else + echo "File does not exist: $ENV_FILE" + echo "Copying .env.production to .env-$DATE" + cp /data/coolify/source/.env.production $ENV_FILE-$DATE + # Generate a secure APP_ID and APP_KEY + sed -i "s|^APP_ID=.*|APP_ID=$(openssl rand -hex 16)|" "$ENV_FILE-$DATE" + sed -i "s|^APP_KEY=.*|APP_KEY=base64:$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" # Generate a secure Postgres DB username and password # Causes issues: database "random-user" does not exist - # sed -i "s|^DB_USERNAME=.*|DB_USERNAME=$(openssl rand -hex 16)|" "$ENV_FILE" - sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE" + # sed -i "s|^DB_USERNAME=.*|DB_USERNAME=$(openssl rand -hex 16)|" "$ENV_FILE-$DATE" + sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" # Generate a secure Redis password - sed -i "s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE" + sed -i "s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" # Generate secure Pusher credentials - sed -i "s|^PUSHER_APP_ID=.*|PUSHER_APP_ID=$(openssl rand -hex 32)|" "$ENV_FILE" - sed -i "s|^PUSHER_APP_KEY=.*|PUSHER_APP_KEY=$(openssl rand -hex 32)|" "$ENV_FILE" - sed -i "s|^PUSHER_APP_SECRET=.*|PUSHER_APP_SECRET=$(openssl rand -hex 32)|" "$ENV_FILE" + sed -i "s|^PUSHER_APP_ID=.*|PUSHER_APP_ID=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" + sed -i "s|^PUSHER_APP_KEY=.*|PUSHER_APP_KEY=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" + sed -i "s|^PUSHER_APP_SECRET=.*|PUSHER_APP_SECRET=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" fi # Merge .env and .env.production. New values will be added to .env -sort -u -t '=' -k 1,1 /data/coolify/source/.env /data/coolify/source/.env.production | sed '/^$/d' >/data/coolify/source/.env.temp && mv /data/coolify/source/.env.temp /data/coolify/source/.env +awk -F '=' '!seen[$1]++' "$ENV_FILE-$DATE" /data/coolify/source/.env.production > $ENV_FILE if [ "$AUTOUPDATE" = "false" ]; then if ! grep -q "AUTOUPDATE=" /data/coolify/source/.env; then @@ -350,7 +399,7 @@ if ! grep -qw "root@coolify" ~/.ssh/authorized_keys; then fi bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" - +rm -f $ENV_FILE-$DATE echo "Waiting for 20 seconds for Coolify to be ready..." sleep 20 diff --git a/other/nightly/upgrade.sh b/other/nightly/upgrade.sh index bce82aaa5..45295a510 100644 --- a/other/nightly/upgrade.sh +++ b/other/nightly/upgrade.sh @@ -11,7 +11,7 @@ curl -fsSL $CDN/docker-compose.prod.yml -o /data/coolify/source/docker-compose.p curl -fsSL $CDN/.env.production -o /data/coolify/source/.env.production # Merge .env and .env.production. New values will be added to .env -sort -u -t '=' -k 1,1 /data/coolify/source/.env /data/coolify/source/.env.production | sed '/^$/d' >/data/coolify/source/.env.temp && mv /data/coolify/source/.env.temp /data/coolify/source/.env +awk -F '=' '!seen[$1]++' /data/coolify/source/.env /data/coolify/source/.env.production > /data/coolify/source/.env.tmp && mv /data/coolify/source/.env.tmp /data/coolify/source/.env # Check if PUSHER_APP_ID or PUSHER_APP_KEY or PUSHER_APP_SECRET is empty in /data/coolify/source/.env if grep -q "PUSHER_APP_ID=$" /data/coolify/source/.env; then diff --git a/resources/views/livewire/boarding/index.blade.php b/resources/views/livewire/boarding/index.blade.php index 2e5fa41c9..7b7ef8c12 100644 --- a/resources/views/livewire/boarding/index.blade.php +++ b/resources/views/livewire/boarding/index.blade.php @@ -28,25 +28,33 @@ -

You don't need to manage your servers anymore. +

+ You don't need to manage your servers anymore. Coolify does - it for you.

-

All configurations are stored on your servers, so - everything works without a connection to Coolify (except integrations and automations).

-

You can get notified on your favourite platforms + it for you. +

+

+ All configurations are stored on your servers, so + everything works without a connection to Coolify (except integrations and automations). +

+

+ You can get notified on your favourite platforms (Discord, - Telegram, Email, etc.) when something goes wrong, or an action is needed from your side.

+ Telegram, Email, etc.) when something goes wrong, or an action is needed from your side. +

- Next + Next @elseif ($currentState === 'select-server-type') - Do you want to deploy your resources to your - or to a ? + Do you want to deploy your resources to your + + or to a + ? Remote Server + @if (!$serverReachable) - Localhost is not reachable with the following public key. -

- Please make sure you have the correct public key in your ~/.ssh/authorized_keys file for - user or skip the boarding process and add a new private key manually to Coolify and to the - server. -
- Check this documentation for further - help. - - Check again - +
+

Server is not reachable

+

Please check the connection details below and correct them if they are + incorrect.

+ +
+ +
+ +

+ Non-root user is experimental: + docs +

+
+
+ +
+

If the connection details are correct, please ensure:

+
    +
  • The correct public key is in your ~/.ssh/authorized_keys + file for the specified user
  • +
  • Or skip the boarding process and manually add a new private key to Coolify and + the server
  • +
+
+ +

+ For more help, check this documentation. +

+ + + + + Check Again + +
@endif

Servers are the main building blocks, as they will host your applications, databases, services, called resources. Any CPU intensive process will use the server's CPU where you are deploying your resources.

-

is the server where Coolify is running on. It is not +

+ is the server where Coolify is running on. It is not recommended to use one server - for everything.

-

is a server reachable through SSH. It can be hosted + for everything. +

+

+ is a server reachable through SSH. It can be hosted at home, or from any cloud - provider.

+ provider. +

@elseif ($currentState === 'private-key') @@ -126,10 +168,7 @@
No - (create - one - for - me) + (create one for me)
@@ -145,20 +184,48 @@
@if (!$serverReachable) - This server is not reachable with the following public key. -

- Please make sure you have the correct public key in your ~/.ssh/authorized_keys file for - user or skip the boarding process and add a new private key manually to Coolify and to the - server. -
- Check this documentation for further - help. - - Check - again - +
+

Server is not reachable

+

Please check the connection details below and correct them if they are + incorrect.

+ +
+ +
+ +

+ Non-root user is experimental: + docs +

+
+
+ +
+

If the connection details are correct, please ensure:

+
    +
  • The correct public key is in your ~/.ssh/authorized_keys + file for the specified user
  • +
  • Or skip the boarding process and manually add a new private key to Coolify and + the server
  • +
+
+ +

+ For more help, check this documentation. +

+ + + + + Check again + +
@endif @@ -180,8 +247,8 @@ label="Name" id="privateKeyName" /> - + @if ($privateKeyType === 'create') ACTION REQUIRED: Copy the 'Public Key' to your @@ -209,27 +276,37 @@
+ label="Name" id="remoteServerName" wire:model="remoteServerName" /> + label="Description" id="remoteServerDescription" + wire:model="remoteServerDescription" />
- - -
- -
Non-root user is experimental: docs. + +
+
+ +
+ +
+ +
Non-root user is + experimental: docs. +
+ id="isCloudflareTunnel" label="Cloudflare Tunnel" wire:model="isCloudflareTunnel" />
Continue @@ -329,5 +406,4 @@
-
diff --git a/scripts/install.sh b/scripts/install.sh index d709efcd1..648f78da0 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -59,9 +59,9 @@ if [ $EUID != 0 ]; then fi case "$OS_TYPE" in -arch | ubuntu | debian | raspbian | centos | fedora | rhel | ol | rocky | sles | opensuse-leap | opensuse-tumbleweed | almalinux | amzn) ;; +arch | ubuntu | debian | raspbian | centos | fedora | rhel | ol | rocky | sles | opensuse-leap | opensuse-tumbleweed | almalinux | amzn | alpine) ;; *) - echo "This script only supports Debian, Redhat, Arch Linux, or SLES based operating systems for now." + echo "This script only supports Debian, Redhat, Arch Linux, Alpine Linux, or SLES based operating systems for now." exit ;; esac @@ -90,6 +90,11 @@ case "$OS_TYPE" in arch) pacman -Sy --noconfirm --needed curl wget git jq >/dev/null || true ;; +alpine) + sed -i '/^#.*\/community/s/^#//' /etc/apk/repositories + apk update >/dev/null + apk add curl wget git jq >/dev/null + ;; ubuntu | debian | raspbian) apt-get update -y >/dev/null apt-get install -y curl wget git jq >/dev/null @@ -172,70 +177,74 @@ if [ -x "$(command -v snap)" ]; then fi if ! [ -x "$(command -v docker)" ]; then - # Almalinux - if [ "$OS_TYPE" == 'almalinux' ]; then - dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo - dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin - if ! [ -x "$(command -v docker)" ]; then - echo "Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 - fi - systemctl start docker - systemctl enable docker - else - set +e - if ! [ -x "$(command -v docker)" ]; then - echo "Docker is not installed. Installing Docker." - # Arch Linux - if [ "$OS_TYPE" = "arch" ]; then - pacman -Sy docker docker-compose --noconfirm - systemctl enable docker.service + case "$OS_TYPE" in + "almalinux") + dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin + if ! [ -x "$(command -v docker)" ]; then + echo "Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 + fi + systemctl start docker + systemctl enable docker + ;; + "alpine") + apk add docker docker-cli-compose + rc-update add docker default + service docker start + if [ -x "$(command -v docker)" ]; then + echo "Docker installed successfully." + else + echo "Failed to install Docker with apk. Try to install it manually." + echo "Please visit https://wiki.alpinelinux.org/wiki/Docker for more information." + exit + fi + ;; + "arch") + pacman -Sy docker docker-compose --noconfirm + systemctl enable docker.service + if [ -x "$(command -v docker)" ]; then + echo "Docker installed successfully." + else + echo "Failed to install Docker with pacman. Try to install it manually." + echo "Please visit https://wiki.archlinux.org/title/docker for more information." + exit + fi + ;; + "amzn") + dnf install docker -y + DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} + mkdir -p $DOCKER_CONFIG/cli-plugins + curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose + chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose + systemctl start docker + systemctl enable docker + if [ -x "$(command -v docker)" ]; then + echo "Docker installed successfully." + else + echo "Failed to install Docker with dnf. Try to install it manually." + echo "Please visit https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/ for more information." + exit + fi + ;; + *) + # Automated Docker installation + curl https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh + if [ -x "$(command -v docker)" ]; then + echo "Docker installed successfully." + else + echo "Docker installation failed with Rancher script. Trying with official script." + curl https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} if [ -x "$(command -v docker)" ]; then echo "Docker installed successfully." else - echo "Failed to install Docker with pacman. Try to install it manually." - echo "Please visit https://wiki.archlinux.org/title/docker for more information." - exit - fi - else - # Amazon Linux 2023 - if [ "$OS_TYPE" = "amzn" ]; then - dnf install docker -y - DOCKER_CONFIG=${DOCKER_CONFIG:-/usr/local/lib/docker} - mkdir -p $DOCKER_CONFIG/cli-plugins - curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o $DOCKER_CONFIG/cli-plugins/docker-compose - chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose - systemctl start docker - systemctl enable docker - if [ -x "$(command -v docker)" ]; then - echo "Docker installed successfully." - else - echo "Failed to install Docker with pacman. Try to install it manually." - echo "Please visit https://wiki.archlinux.org/title/docker for more information." - exit - fi - else - # Automated Docker installation - curl https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh - if [ -x "$(command -v docker)" ]; then - echo "Docker installed successfully." - else - echo "Docker installation failed with Rancher script. Trying with official script." - curl https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} - if [ -x "$(command -v docker)" ]; then - echo "Docker installed successfully." - else - echo "Docker installation failed with official script." - echo "Maybe your OS is not supported?" - echo "Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." - exit 1 - fi - fi + echo "Docker installation failed with official script." + echo "Maybe your OS is not supported?" + echo "Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." + exit 1 fi fi - fi - set -e - fi + esac fi echo -e "-------------" @@ -267,17 +276,50 @@ if ! jq -s '.[0] * .[1]' /etc/docker/daemon.json /etc/docker/daemon.json.coolify fi mv "$TEMP_FILE" /etc/docker/daemon.json +restart_docker_service() { + + # Check if systemctl is available + if command -v systemctl >/dev/null 2>&1; then + echo "Using systemctl to restart Docker..." + systemctl restart docker + + if [ $? -eq 0 ]; then + echo "Docker restarted successfully using systemctl." + else + echo "Failed to restart Docker using systemctl." + return 1 + fi + + # Check if service command is available + elif command -v service >/dev/null 2>&1; then + echo "Using service command to restart Docker..." + service docker restart + + if [ $? -eq 0 ]; then + echo "Docker restarted successfully using service." + else + echo "Failed to restart Docker using service." + return 1 + fi + + # If neither systemctl nor service is available + else + echo "Neither systemctl nor service command is available on this system." + return 1 + fi +} + if [ -s /etc/docker/daemon.json.original-"$DATE" ]; then DIFF=$(diff <(jq --sort-keys . /etc/docker/daemon.json) <(jq --sort-keys . /etc/docker/daemon.json.original-"$DATE")) if [ "$DIFF" != "" ]; then echo "Docker configuration updated, restart docker daemon..." - systemctl restart docker + restart_docker_service else echo "Docker configuration is up to date." fi else echo "Docker configuration updated, restart docker daemon..." - systemctl restart docker + restart_docker_service fi echo -e "-------------" @@ -296,28 +338,35 @@ curl -fsSL $CDN/.env.production -o /data/coolify/source/.env.production curl -fsSL $CDN/upgrade.sh -o /data/coolify/source/upgrade.sh # Copy .env.example if .env does not exist -if [ ! -f $ENV_FILE ]; then - cp /data/coolify/source/.env.production $ENV_FILE - # Generate a secure APP_ID and APP_KEY - sed -i "s|^APP_ID=.*|APP_ID=$(openssl rand -hex 16)|" "$ENV_FILE" - sed -i "s|^APP_KEY=.*|APP_KEY=base64:$(openssl rand -base64 32)|" "$ENV_FILE" +if [ -f $ENV_FILE ]; then + echo "File exists: $ENV_FILE" + echo "Copying .env to .env-$DATE" + cp $ENV_FILE $ENV_FILE-$DATE +else + echo "File does not exist: $ENV_FILE" + echo "Copying .env.production to .env-$DATE" + cp /data/coolify/source/.env.production $ENV_FILE-$DATE + # Generate a secure APP_ID and APP_KEY + sed -i "s|^APP_ID=.*|APP_ID=$(openssl rand -hex 16)|" "$ENV_FILE-$DATE" + sed -i "s|^APP_KEY=.*|APP_KEY=base64:$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" # Generate a secure Postgres DB username and password # Causes issues: database "random-user" does not exist - # sed -i "s|^DB_USERNAME=.*|DB_USERNAME=$(openssl rand -hex 16)|" "$ENV_FILE" - sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE" + # sed -i "s|^DB_USERNAME=.*|DB_USERNAME=$(openssl rand -hex 16)|" "$ENV_FILE-$DATE" + sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" # Generate a secure Redis password - sed -i "s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE" + sed -i "s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=$(openssl rand -base64 32)|" "$ENV_FILE-$DATE" # Generate secure Pusher credentials - sed -i "s|^PUSHER_APP_ID=.*|PUSHER_APP_ID=$(openssl rand -hex 32)|" "$ENV_FILE" - sed -i "s|^PUSHER_APP_KEY=.*|PUSHER_APP_KEY=$(openssl rand -hex 32)|" "$ENV_FILE" - sed -i "s|^PUSHER_APP_SECRET=.*|PUSHER_APP_SECRET=$(openssl rand -hex 32)|" "$ENV_FILE" + sed -i "s|^PUSHER_APP_ID=.*|PUSHER_APP_ID=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" + sed -i "s|^PUSHER_APP_KEY=.*|PUSHER_APP_KEY=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" + sed -i "s|^PUSHER_APP_SECRET=.*|PUSHER_APP_SECRET=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" fi # Merge .env and .env.production. New values will be added to .env -sort -u -t '=' -k 1,1 /data/coolify/source/.env /data/coolify/source/.env.production | sed '/^$/d' >/data/coolify/source/.env.temp && mv /data/coolify/source/.env.temp /data/coolify/source/.env +echo "Updating .env with new values (if necessary)..." +awk -F '=' '!seen[$1]++' "$ENV_FILE-$DATE" /data/coolify/source/.env.production > $ENV_FILE if [ "$AUTOUPDATE" = "false" ]; then if ! grep -q "AUTOUPDATE=" /data/coolify/source/.env; then @@ -350,9 +399,13 @@ if ! grep -qw "root@coolify" ~/.ssh/authorized_keys; then fi bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}" - +rm -f $ENV_FILE-$DATE echo "Waiting for 20 seconds for Coolify to be ready..." sleep 20 echo "Please visit http://$(curl -4s https://ifconfig.io):8000 to get started." echo -e "\nCongratulations! Your Coolify instance is ready to use.\n" + +echo -e "Make sure you backup your /data/coolify/source/.env file to a safe location, outside of this server.\n" +cp /data/coolify/source/.env /data/coolify/source/.env.backup +echo -e "Your .env file has been copied to /data/coolify/source/.env.backup\n" diff --git a/scripts/upgrade.sh b/scripts/upgrade.sh index d46729443..a7844f413 100644 --- a/scripts/upgrade.sh +++ b/scripts/upgrade.sh @@ -11,8 +11,7 @@ curl -fsSL $CDN/docker-compose.prod.yml -o /data/coolify/source/docker-compose.p curl -fsSL $CDN/.env.production -o /data/coolify/source/.env.production # Merge .env and .env.production. New values will be added to .env -sort -u -t '=' -k 1,1 /data/coolify/source/.env /data/coolify/source/.env.production | sed '/^$/d' >/data/coolify/source/.env.temp && mv /data/coolify/source/.env.temp /data/coolify/source/.env - +awk -F '=' '!seen[$1]++' /data/coolify/source/.env /data/coolify/source/.env.production > /data/coolify/source/.env.tmp && mv /data/coolify/source/.env.tmp /data/coolify/source/.env # Check if PUSHER_APP_ID or PUSHER_APP_KEY or PUSHER_APP_SECRET is empty in /data/coolify/source/.env if grep -q "PUSHER_APP_ID=$" /data/coolify/source/.env; then sed -i "s|PUSHER_APP_ID=.*|PUSHER_APP_ID=$(openssl rand -hex 32)|g" /data/coolify/source/.env diff --git a/versions.json b/versions.json index b9c235577..9d69c9563 100644 --- a/versions.json +++ b/versions.json @@ -1,13 +1,13 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.332" + "version": "4.0.0-beta.333" }, "nightly": { - "version": "4.0.0-beta.333" + "version": "4.0.0-beta.334" }, "helper": { "version": "1.0.1" } } -} \ No newline at end of file +}