From 680d2078538cefa26cb6edf9affe4f021dfc23bb Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Thu, 4 Dec 2025 17:11:33 +0100 Subject: [PATCH 01/19] make install.sh more idempotent, replace placeholder with random values in .env --- deployment/bare_metal/.env.dist | 212 ++++++++++++++++++---------- deployment/bare_metal/start.sh | 6 +- deployment/hetzner_cloud/install.sh | 128 ++++++++++++++--- dlt-connector/src/config/schema.ts | 2 +- 4 files changed, 255 insertions(+), 93 deletions(-) diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index 8341133c9..6df408d71 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -1,7 +1,12 @@ # Need to adjust! +# Will be seen on login and from other communities if dht and federation modules are active COMMUNITY_NAME="Your community name" COMMUNITY_DESCRIPTION="Short Description from your Community." +# your domain name, without protocol (without https:// or http:// ) +# domain name should be configured in your dns records to point to this server +# hetzner_cloud/install.sh will be acquire a SSL-certificate via letsencrypt for this domain COMMUNITY_HOST=gddhost.tld +# used in E-Mails and some error message, should be the email address of your own support (team) COMMUNITY_SUPPORT_MAIL=support@supportmail.com # setup email account for sending gradido system messages to users @@ -12,10 +17,40 @@ EMAIL_PASSWORD=1234 EMAIL_SMTP_HOST=smtp.lustig.de EMAIL_SMTP_PORT=587 -BACKEND_PORT=4000 - +# Federation, Settings for transactions with other communities # if set to true allow sending gradidos to another communities FEDERATION_XCOM_SENDCOINS_ENABLED=false +# if set to true, allow redeeming gradido link from another community +CROSS_TX_REDEEM_LINK_ACTIVE=false + +# if you set the value of FEDERATION_DHT_TOPIC, the DHT hyperswarm will start to announce and listen +# on an hash created from this topic +# need for discover other communities +# get the correct topic from Gradido Academy, GRADIDO_HUB is our test topic +FEDERATION_DHT_TOPIC=GRADIDO_HUB + +# Advanced Server Setup + +# Logging +LOG_LEVEL=info +GRADIDO_LOG_PATH=/home/gradido/gradido/deployment/bare_metal/log +TYPEORM_LOGGING_RELATIVE_PATH=../deployment/bare_metal/log/typeorm.backend.log + +# Need adjustments for test system +# protocol for community host, on production usually https, on local dev usually http +URL_PROTOCOL=https + +# only for test server +DEPLOY_SEED_DATA=false +# test email +# if true all email will be send to EMAIL_TEST_RECEIVER instead of email address of user +EMAIL_TEST_MODUS=false +EMAIL_TEST_RECEIVER=test_team@gddhost.tld + +# webhook for auto update on github repository changes +WEBHOOK_GITHUB_BRANCH=master + +# Business Logic # how many minutes email verification code is valid # also used for password reset code @@ -23,36 +58,8 @@ EMAIL_CODE_VALID_TIME=1440 # how many minutes user must wait before he can request the email verification code again # also used for password reset code EMAIL_CODE_REQUEST_TIME=10 - -# Need to adjust by updates -# config versions -DATABASE_CONFIG_VERSION=v1.2022-03-18 -BACKEND_CONFIG_VERSION=v23.2024-04-04 -FRONTEND_CONFIG_VERSION=v6.2024-02-27 -ADMIN_CONFIG_VERSION=v2.2024-01-04 -FEDERATION_CONFIG_VERSION=v2.2023-08-24 -FEDERATION_DHT_CONFIG_VERSION=v4.2024-01-17 -FEDERATION_DHT_TOPIC=GRADIDO_HUB - -# Need adjustments for test system -URL_PROTOCOL=https -# start script -# only for test server -DEPLOY_SEED_DATA=false -# test email -# if true all email will be send to EMAIL_TEST_RECEIVER instead of email address of user -EMAIL_TEST_MODUS=false -EMAIL_TEST_RECEIVER=test_team@gradido.net -USE_CRYPTO_WORKER=true - -# Logging -LOG_LEVEL=info -GRADIDO_LOG_PATH=/home/gradido/gradido/deployment/bare_metal/log -TYPEORM_LOGGING_RELATIVE_PATH=../deployment/bare_metal/log/typeorm.backend.log - -# webhook -WEBHOOK_GITHUB_SECRET=secret -WEBHOOK_GITHUB_BRANCH=master +# login expire time +JWT_EXPIRES_IN=10m # frontend and admin paths, usually don't need changes # used in nginx config and for links in emails @@ -66,44 +73,19 @@ EMAIL_LINK_SETPASSWORD_PATH=/reset-password/ EMAIL_LINK_FORGOTPASSWORD_PATH=/forgot-password EMAIL_LINK_OVERVIEW_PATH=/overview ADMIN_AUTH_PATH=/admin/authenticate?token= -GRAPHQL_PATH=/graphql - -# login expire time -JWT_SECRET=secret123 -JWT_EXPIRES_IN=10m +# need to change when frontend is hosted on a different domain as the backend +WALLET_URL=$URL_PROTOCOL://$COMMUNITY_HOST +GRAPHQL_URI=$URL_PROTOCOL://$COMMUNITY_HOST/graphql # Federation -# if you set the value of FEDERATION_DHT_TOPIC, the DHT hyperswarm will start to announce and listen -# on an hash created from this topic # FEDERATION_DHT_TOPIC=GRADIDO_HUB -# FEDERATION_DHT_SEED=64ebcb0e3ad547848fef4197c6e2332f +# # the api port is the baseport, which will be added with the api-version, e.g. 1_0 = 5010 FEDERATION_COMMUNITY_API_PORT=5000 -FEDERATION_VALIDATE_COMMUNITY_TIMER=60000 # comma separated list of api-versions, which cause starting several federation modules FEDERATION_COMMUNITY_APIS=1_0 -# externe gradido services (more added in future) -GDT_ACTIVE=false - -AUTO_POLL_INTERVAL=30000 - -# DLT-Connector (still in develop) -DLT_ACTIVE=false -DLT_CONNECTOR_PORT=6010 -DLT_NODE_SERVER_PORT=8340 -DLT_NODE_SERVER_URL=$URL_PROTOCOL://$COMMUNITY_HOST/dlt -DLT_GRADIDO_NODE_SERVER_HOME_FOLDER=/home/gradido/.gradido - -# used for combining a newsletter on klicktipp with this gradido community -# if used, user will be subscribed on register and can unsubscribe in his account -KLICKTIPP=false -KLICKTIPP_USER=gradido_test -KLICKTIPP_PASSWORD=secret321 -KLICKTIPP_APIKEY_DE=SomeFakeKeyDE -KLICKTIPP_APIKEY_EN=SomeFakeKeyEN - # Meta data in frontend pages, important when shared via facebook or twitter or for search engines META_TITLE_DE="Gradido – Dein Dankbarkeitskonto" META_TITLE_EN="Gradido - Your gratitude account" @@ -113,6 +95,34 @@ META_KEYWORDS_DE="Grundeinkommen, Währung, Dankbarkeit, Schenk-Ökonomie, Natü META_KEYWORDS_EN="Basic Income, Currency, Gratitude, Gift Economy, Natural Economy of Life, Economy, Ecology, Potential Development, Giving and Thanking, Cycle of Life, Monetary System" META_AUTHOR="Bernd Hückstädt - Gradido-Akademie" +# externe gradido services + +GDT_ACTIVE=false + +# DLT-Connector (still in develop) +# verify transaction additional via gradido blockchain +DLT_ACTIVE=false +DLT_CONNECTOR_PORT=6010 +DLT_NODE_SERVER_PORT=8340 +DLT_GRADIDO_NODE_SERVER_HOME_FOLDER=/home/gradido/.gradido + +# HIERO used from dlt-connector +HIERO_HEDERA_NETWORK=testnet +# https://docs.hedera.com/hedera/networks/testnet/testnet-access +HIERO_OPERATOR_ID= +HIERO_OPERATOR_KEY= + +# for inspector from outside of server +DLT_NODE_SERVER_URL=$URL_PROTOCOL://$COMMUNITY_HOST/dlt + +# used for combining a newsletter on klicktipp with this gradido community +# if used, user will be subscribed on register and can unsubscribe in his account +KLICKTIPP=false +KLICKTIPP_USER=gradido_test +KLICKTIPP_PASSWORD=secret321 +KLICKTIPP_APIKEY_DE=SomeFakeKeyDE +KLICKTIPP_APIKEY_EN=SomeFakeKeyEN + # update page shown while updating gradido # page will be fed with status changes NGINX_UPDATE_PAGE_ROOT=/home/gradido/gradido/deployment/bare_metal/nginx/update-page @@ -124,24 +134,82 @@ NGINX_SSL_DHPARAM=/etc/letsencrypt/ssl-dhparams.pem NGINX_SSL_INCLUDE=/etc/letsencrypt/options-ssl-nginx.conf NGINX_REWRITE_LEGACY_URLS=false -# LEGACY -WEBHOOK_ELOPAGE_SECRET=secret +# Services +BACKEND_PORT=4000 # GMS +# Speak with Gradido Academy to get access to GMS GMS_ACTIVE=false -# Coordinates of Illuminz test instance -#GMS_API_URL=http://54.176.169.179:3071 -GMS_API_URL=http://localhost:4044/ -GMS_DASHBOARD_URL=http://localhost:8080/ -GMS_WEBHOOK_SECRET=secret +GMS_API_URL=https://gms-stage.gradido.net/gms +GMS_DASHBOARD_URL=https://gms-stage.gradido.net/ +GMS_USER_SEARCH_FRONTEND_ROUTE=user-search +# set your own or placeholder webhook_secret will be replaced by start.sh +GMS_WEBHOOK_SECRET=webhook_secret GMS_CREATE_USER_THROW_ERRORS=false # HUMHUB +# Host your own humhub Server HUMHUB_ACTIVE=false -HUMHUB_API_URL=https://community.gradido.net -HUMHUB_JWT_KEY= +HUMHUB_API_URL=https://your-humhub-domain.tld +# Humhub jwt key, setup together with humhub +# set your own or placeholder jwt_secret will be replaced by start.sh +HUMHUB_JWT_KEY=jwt_secret # OPENAI +# you need a paid openai account to use this feature OPENAI_ACTIVE=false -OPENAI_API_KEY='' -OPENAI_ASSISTANT_ID=asst_MF5cchZr7wY7rNXayuWvZFsM \ No newline at end of file +# assistant id for your openai assistant +OPENAI_ASSISTANT_ID= +# your api key form openai +OPENAI_API_KEY= + +# Performance Settings + +# in milliseconds, how often inspector and frontend ask on some views for new data +AUTO_POLL_INTERVAL=60000 +# set to true if password encryption should take place in another thread, which don't block the main loop, true is recommended +USE_CRYPTO_WORKER=true +# in milliseconds, how often the other communities should be checked if still online and reachable +FEDERATION_VALIDATE_COMMUNITY_TIMER=60000 + +# Security Settings, placeholder (jwt_secret, webhook_secret, binary8_secret, binary16_secret, binary32_secret) +# will be replaced by start.sh + +JWT_SECRET=jwt_secret +# secret for webhook, must be set here and in github.com webhook +WEBHOOK_GITHUB_SECRET=webhook_secret +# basic for key pair generation for federation, maximal 64 characters +FEDERATION_DHT_SEED=binary32_secret +WEBHOOK_ELOPAGE_SECRET=webhook_secret +# keys for dlt +GRADIDO_BLOCKCHAIN_CRYPTO_APP_SECRET=binary8_secret +GRADIDO_BLOCKCHAIN_SERVER_CRYPTO_KEY=binary16_secret +HOME_COMMUNITY_SEED=binary32_secret + +# Server Settings needed if modules are hosted on different servers (non-default setup) + +# GUI-Module Configs (with nginx-routing always running on COMMUNITY_HOST) +ADMIN_MODULE_PROTOCOL=$URL_PROTOCOL +ADMIN_MODULE_HOST=$COMMUNITY_HOST +ADMIN_MODULE_PORT=8080 + +FRONTEND_MODULE_PROTOCOL=$URL_PROTOCOL +FRONTEND_MODULE_HOST=$COMMUNITY_HOST +FRONTEND_MODULE_PORT=3000 + +# Non-GUI-Module Configs (with nginx-routing always running on localhost in case of on bare metal) +BACKEND_MODULE_PROTOCOL=http +BACKEND_MODULE_HOST=localhost +BACKEND_PORT=4000 + +DHT_MODULE_PROTOCOL=http +DHT_MODULE_HOST=localhost +DHT_MODULE_PORT=5000 + +DLT_MODULE_PROTOCOL=http +DLT_MODULE_HOST=localhost +DLT_MODULE_PORT=6010 + +FEDERATION_MODULE_PROTOCOL=http +FEDERATION_MODULE_HOST=localhost +FEDERATION_MODULE_PORT=5010 \ No newline at end of file diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh index 80ef55d39..194e879e6 100755 --- a/deployment/bare_metal/start.sh +++ b/deployment/bare_metal/start.sh @@ -299,7 +299,7 @@ done # Install all node_modules log_step 'Installing node_modules' -bun install +bun install --frozen-lockfile # build all modules log_step 'build all modules' @@ -309,12 +309,12 @@ turbo build --env-mode=loose --concurrency=$(nproc) if [ "$DLT_ACTIVE" = true ]; then log_step 'build inspector' cd $PROJECT_ROOT/inspector - bun install + bun install --frozen-lockfile bun run build log_step 'build dlt-connector' cd $PROJECT_ROOT/dlt-connector - bun install + bun install --frozen-lockfile bun run build cd $PROJECT_ROOT diff --git a/deployment/hetzner_cloud/install.sh b/deployment/hetzner_cloud/install.sh index e5fe29f81..4ddcf44e4 100755 --- a/deployment/hetzner_cloud/install.sh +++ b/deployment/hetzner_cloud/install.sh @@ -1,7 +1,28 @@ #!/bin/bash +# stop if something fails +set -euo pipefail + +log_error() { + local message="$1" + echo -e "\e[31m$message\e[0m" >&3 # red in console +} + +# called always on error, log error really visible with ascii art in red on console and html +# stop script execution +onError() { + local exit_code=$? + log_error "Command failed!" + log_error " /\\_/\\ Line: $(caller 0)" + log_error "( x.x ) Exit Code: $exit_code" + log_error " > < Offending command: '$BASH_COMMAND'" + log_error "" + exit 1 +} +trap onError ERR + # check for parameter if [ -z "$1" ]; then - echo "Usage: Please provide a branch name as the first argument." + log_error "Usage: Please provide a branch name as the first argument." exit 1 fi @@ -19,25 +40,96 @@ LOCAL_SCRIPT_DIR=$(dirname $LOCAL_SCRIPT_PATH) PROJECT_ROOT=$SCRIPT_DIR/.. set +o allexport +# Replace placeholder secrets in .env +echo 'Replace placeholder secrets in .env' +# Load .env or .env.dist if not present +# NOTE: all config values will be in process.env when starting +# the services and will therefore take precedence over the .env +if [ -f "$SCRIPT_PATH/.env" ]; then + ENV_FILE = $SCRIPT_PATH/.env + + # --- Secret Generators ------------------------------------------------------- + + gen_jwt_secret() { + # 32 Character, URL-safe: A-Z a-z 0-9 _ - + tr -dc 'A-Za-z0-9_-' < /dev/urandom | head -c 32 + } + + gen_webhook_secret() { + # URL-safe, longer security (40 chars) + tr -dc 'A-Za-z0-9_-' < /dev/urandom | head -c 40 + } + + gen_binary_secret() { + local bytes="$1" + # Hex -> 2 chars pro byte + openssl rand -hex "$bytes" + } + + # --- Mapping of Placeholder -> Function -------------------------------------- + + generate_secret_for() { + case "$1" in + jwt_secret) + gen_jwt_secret + ;; + webhook_secret) + gen_webhook_secret + ;; + binary8_secret) + gen_binary_secret 8 + ;; + binary16_secret) + gen_binary_secret 16 + ;; + binary32_secret) + gen_binary_secret 32 + ;; + *) + echo "Unknown Placeholder: $1" >&2 + exit 1 + ;; + esac + } + + # --- Placeholder List -------------------------------------------------------- + + placeholders=( + "jwt_secret" + "webhook_secret" + "binary8_secret" + "binary16_secret" + "binary32_secret" + ) + + # --- Processing in .env ------------------------------------------------- + + TMP_FILE="${ENV_FILE}.tmp" + cp "$ENV_FILE" "$TMP_FILE" + + for ph in "${placeholders[@]}"; do + # Secret generate + new_value="$(generate_secret_for "$ph")" + + # Only replace lines that do NOT start with # + sed -i "/^[[:space:]]*#/! s/$ph/$new_value/g" "$TMP_FILE" + done + + # Write back + mv "$TMP_FILE" "$ENV_FILE" +fi + # If install.sh will be called more than once -# We have to load the backend .env to get DB_USERNAME, DB_PASSWORD AND JWT_SECRET -# and the dht-node .env to get FEDERATION_DHT_SEED +# We have to load the backend .env to get DB_USERNAME and DB_PASSWORD export_var(){ export $1=$(grep -v '^#' $PROJECT_ROOT/backend/.env | grep -e "$1" | sed -e 's/.*=//') - export $1=$(grep -v '^#' $PROJECT_ROOT/dht-node/.env | grep -e "$1" | sed -e 's/.*=//') } if [ -f "$PROJECT_ROOT/backend/.env" ]; then export_var 'DB_USER' export_var 'DB_PASSWORD' - export_var 'JWT_SECRET' fi -if [ -f "$PROJECT_ROOT/dht-node/.env" ]; then - export_var 'FEDERATION_DHT_SEED' -fi - - # Load .env or .env.dist if not present # NOTE: all config values will be in process.env when starting # the services and will therefore take precedence over the .env @@ -97,15 +189,17 @@ systemctl restart fail2ban rm /etc/nginx/sites-enabled/default envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $SCRIPT_PATH/nginx/sites-available/gradido.conf.template > $SCRIPT_PATH/nginx/sites-available/gradido.conf envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $SCRIPT_PATH/nginx/sites-available/update-page.conf.template > $SCRIPT_PATH/nginx/sites-available/update-page.conf -mkdir $SCRIPT_PATH/nginx/sites-enabled -ln -s $SCRIPT_PATH/nginx/sites-available/update-page.conf $SCRIPT_PATH/nginx/sites-enabled/default -ln -s $SCRIPT_PATH/nginx/sites-enabled/default /etc/nginx/sites-enabled -ln -s $SCRIPT_PATH/nginx/common /etc/nginx/ -rmdir /etc/nginx/conf.d -ln -s $SCRIPT_PATH/nginx/conf.d /etc/nginx/ +mkdir -p $SCRIPT_PATH/nginx/sites-enabled +ln -sf $SCRIPT_PATH/nginx/sites-available/update-page.conf $SCRIPT_PATH/nginx/sites-enabled/default +ln -sf $SCRIPT_PATH/nginx/sites-enabled/default /etc/nginx/sites-enabled +ln -sf $SCRIPT_PATH/nginx/common /etc/nginx/ +if [ -e /etc/nginx/conf.d ] && [ ! -L /etc/nginx/conf.d ]; then + rm -rf /etc/nginx/conf.d + ln -s $SCRIPT_PATH/nginx/conf.d /etc/nginx/ +fi # Make nginx restart automatic -mkdir /etc/systemd/system/nginx.service.d +mkdir -p /etc/systemd/system/nginx.service.d # Define the content to be put into the override.conf file CONFIG_CONTENT="[Unit] StartLimitIntervalSec=500 diff --git a/dlt-connector/src/config/schema.ts b/dlt-connector/src/config/schema.ts index 3abb84f6a..ef4558545 100644 --- a/dlt-connector/src/config/schema.ts +++ b/dlt-connector/src/config/schema.ts @@ -37,7 +37,7 @@ export const configSchema = v.object({ GRADIDO_BLOCKCHAIN_SERVER_CRYPTO_KEY: hex16Schema, HOME_COMMUNITY_SEED: v.pipe( hexSchema, - v.length(64, 'expect seed length minimum 64 characters (32 Bytes)'), + v.length(64, 'expect seed length 64 characters (32 Bytes)'), v.transform((input: string) => MemoryBlock.fromHex(input)), ), HIERO_HEDERA_NETWORK: v.optional( From 389c44e5461f2e8c26886a758e9780823fe19227 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 09:06:02 +0100 Subject: [PATCH 02/19] set COMMUNITY_HOST to localhost in deploy test docker --- deployment/bare_metal/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deployment/bare_metal/Dockerfile b/deployment/bare_metal/Dockerfile index 521dabb6c..1f75a06c9 100644 --- a/deployment/bare_metal/Dockerfile +++ b/deployment/bare_metal/Dockerfile @@ -40,6 +40,8 @@ ENV BRANCH_NAME=$BRANCH_NAME RUN git clone https://github.com/gradido/gradido.git --branch $BRANCH_NAME RUN cp /app/gradido/deployment/bare_metal/.env.dist /app/gradido/deployment/bare_metal/.env RUN sed -i 's/^URL_PROTOCOL=https$/URL_PROTOCOL=http/' /app/gradido/deployment/bare_metal/.env +RUN sed -i 's/^COMMUNITY_HOST=gddhost.tld$/COMMUNITY_HOST=localhost/' /app/gradido/deployment/bare_metal/.env + # setup nginx WORKDIR /app/gradido/deployment/bare_metal/nginx From b4a7b36dc8c4cee504177c6693d262b71c009a50 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 09:16:58 +0100 Subject: [PATCH 03/19] make grass optional, debug frontend .env --- deployment/bare_metal/.env.dist | 4 +++ deployment/bare_metal/install-missing-deps.sh | 25 ++++++++++--------- deployment/bare_metal/start.sh | 1 + 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index 6df408d71..9377fa7a2 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -31,6 +31,10 @@ FEDERATION_DHT_TOPIC=GRADIDO_HUB # Advanced Server Setup +# SCSS Parsing +# grass speed up frontend building, but needs some time for the first setup because it is a rust program which need to be compiled +USE_GRASS=false + # Logging LOG_LEVEL=info GRADIDO_LOG_PATH=/home/gradido/gradido/deployment/bare_metal/log diff --git a/deployment/bare_metal/install-missing-deps.sh b/deployment/bare_metal/install-missing-deps.sh index 4d4fef813..1eb2d616e 100644 --- a/deployment/bare_metal/install-missing-deps.sh +++ b/deployment/bare_metal/install-missing-deps.sh @@ -56,19 +56,20 @@ then fi # rust and grass -if ! command -v cargo > /dev/null -then - echo "'cargo' is missing, will be installed now!" - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - export CARGO_HOME="$HOME/.cargo" - export PATH="$CARGO_HOME/bin:$PATH" +if [ "$USE_GRASS" = true ]; then + if ! command -v cargo > /dev/null + then + echo "'cargo' is missing, will be installed now!" + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + export CARGO_HOME="$HOME/.cargo" + export PATH="$CARGO_HOME/bin:$PATH" + fi + if ! command -v grass > /dev/null + then + echo "'grass' is missing, will be installed now!" + cargo install grass + fi fi -if ! command -v grass > /dev/null -then - echo "'grass' is missing, will be installed now!" - cargo install grass -fi - # redis if ! command -v redis-cli --version > /dev/null then diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh index 194e879e6..4e4ac8e55 100755 --- a/deployment/bare_metal/start.sh +++ b/deployment/bare_metal/start.sh @@ -303,6 +303,7 @@ bun install --frozen-lockfile # build all modules log_step 'build all modules' +log_warn cat $PROJECT_ROOT/frontend/.env turbo build --env-mode=loose --concurrency=$(nproc) # build inspector and dlt-connector From 8c6cb746fea55a888035f0c7178cd6b12f06da10 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 09:25:32 +0100 Subject: [PATCH 04/19] fix debug --- deployment/bare_metal/start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh index 4e4ac8e55..3375f4b9c 100755 --- a/deployment/bare_metal/start.sh +++ b/deployment/bare_metal/start.sh @@ -303,7 +303,7 @@ bun install --frozen-lockfile # build all modules log_step 'build all modules' -log_warn cat $PROJECT_ROOT/frontend/.env +cat $PROJECT_ROOT/frontend/.env turbo build --env-mode=loose --concurrency=$(nproc) # build inspector and dlt-connector From 3d8e94b36926d1d8bed7861dc96f414198e99f6b Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 09:41:04 +0100 Subject: [PATCH 05/19] remove CONFIG_VERSION from env templates --- admin/.env.template | 2 -- backend/.env.template | 2 -- database/.env.template | 2 -- dht-node/.env.template | 4 ---- federation/.env.template | 3 --- frontend/.env.template | 2 -- 6 files changed, 15 deletions(-) diff --git a/admin/.env.template b/admin/.env.template index 24725f279..4a65b5a35 100644 --- a/admin/.env.template +++ b/admin/.env.template @@ -1,5 +1,3 @@ -CONFIG_VERSION=$ADMIN_CONFIG_VERSION - COMMUNITY_HOST=$COMMUNITY_HOST URL_PROTOCOL=$URL_PROTOCOL WALLET_AUTH_PATH=$WALLET_AUTH_PATH diff --git a/backend/.env.template b/backend/.env.template index 98090546d..71a3b049f 100644 --- a/backend/.env.template +++ b/backend/.env.template @@ -1,5 +1,3 @@ -# must match the CONFIG_VERSION.EXPECTED definition in scr/config/index.ts - # Server JWT_SECRET=$JWT_SECRET JWT_EXPIRES_IN=$JWT_EXPIRES_IN diff --git a/database/.env.template b/database/.env.template index b5aebba8f..48343a569 100644 --- a/database/.env.template +++ b/database/.env.template @@ -1,5 +1,3 @@ -CONFIG_VERSION=$DATABASE_CONFIG_VERSION - DB_HOST=127.0.0.1 DB_PORT=3306 DB_USER=$DB_USER diff --git a/dht-node/.env.template b/dht-node/.env.template index ad5765f96..e2bcc545d 100644 --- a/dht-node/.env.template +++ b/dht-node/.env.template @@ -1,6 +1,3 @@ -# must match the CONFIG_VERSION.EXPECTED definition in scr/config/index.ts -CONFIG_VERSION=$FEDERATION_DHT_CONFIG_VERSION - # Database DB_HOST=127.0.0.1 DB_PORT=3306 @@ -14,7 +11,6 @@ COMMUNITY_NAME=$COMMUNITY_NAME COMMUNITY_DESCRIPTION=$COMMUNITY_DESCRIPTION # Federation -FEDERATION_DHT_CONFIG_VERSION=$FEDERATION_DHT_CONFIG_VERSION # if you set the value of FEDERATION_DHT_TOPIC, the DHT hyperswarm will start to announce and listen # on an hash created from this topic FEDERATION_DHT_TOPIC=$FEDERATION_DHT_TOPIC diff --git a/federation/.env.template b/federation/.env.template index a4ac298ef..ffd996135 100644 --- a/federation/.env.template +++ b/federation/.env.template @@ -1,6 +1,3 @@ -# must match the CONFIG_VERSION.EXPECTED definition in scr/config/index.ts -CONFIG_VERSION=$FEDERATION_CONFIG_VERSION - LOG_LEVEL=$LOG_LEVEL # this is set fix to false, because it is important for 'production' environments. only set to true if a graphql-playground should be in use GRAPHIQL=false diff --git a/frontend/.env.template b/frontend/.env.template index 4fa775098..553d92ba2 100644 --- a/frontend/.env.template +++ b/frontend/.env.template @@ -1,5 +1,3 @@ -CONFIG_VERSION=$FRONTEND_CONFIG_VERSION - # Endpoints GRAPHQL_PATH=$GRAPHQL_PATH ADMIN_AUTH_PATH=$ADMIN_AUTH_PATH From 572f504c9b13914030b7fb2cfafb8d9d2f6793f9 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 09:41:14 +0100 Subject: [PATCH 06/19] change debug code --- deployment/bare_metal/start.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh index 3375f4b9c..81b987909 100755 --- a/deployment/bare_metal/start.sh +++ b/deployment/bare_metal/start.sh @@ -303,6 +303,9 @@ bun install --frozen-lockfile # build all modules log_step 'build all modules' +echo "PROJECT_ROOT='$PROJECT_ROOT'" +echo "Checking: $PROJECT_ROOT/frontend/.env" +ls -l $PROJECT_ROOT/frontend cat $PROJECT_ROOT/frontend/.env turbo build --env-mode=loose --concurrency=$(nproc) From 6ac478c4c08d393979eb0d2b82a87afc48118627 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 09:49:46 +0100 Subject: [PATCH 07/19] replace GRAPHQL_PATH with GRAPHQL_URI as default in .env.dist --- deployment/bare_metal/.env.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index 9377fa7a2..e738feec1 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -79,7 +79,7 @@ EMAIL_LINK_OVERVIEW_PATH=/overview ADMIN_AUTH_PATH=/admin/authenticate?token= # need to change when frontend is hosted on a different domain as the backend WALLET_URL=$URL_PROTOCOL://$COMMUNITY_HOST -GRAPHQL_URI=$URL_PROTOCOL://$COMMUNITY_HOST/graphql +GRAPHQL_PATH=/graphql # Federation # FEDERATION_DHT_TOPIC=GRADIDO_HUB From c911b80d7655eea2fd226c62a42d8bbec1fb9013 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 10:51:34 +0100 Subject: [PATCH 08/19] remove debug log --- deployment/bare_metal/start.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh index 81b987909..194e879e6 100755 --- a/deployment/bare_metal/start.sh +++ b/deployment/bare_metal/start.sh @@ -303,10 +303,6 @@ bun install --frozen-lockfile # build all modules log_step 'build all modules' -echo "PROJECT_ROOT='$PROJECT_ROOT'" -echo "Checking: $PROJECT_ROOT/frontend/.env" -ls -l $PROJECT_ROOT/frontend -cat $PROJECT_ROOT/frontend/.env turbo build --env-mode=loose --concurrency=$(nproc) # build inspector and dlt-connector From ac50671e75b7730cbd000cc05ae1bf7df485fee7 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 11:42:37 +0100 Subject: [PATCH 09/19] update readme --- deployment/hetzner_cloud/README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/deployment/hetzner_cloud/README.md b/deployment/hetzner_cloud/README.md index a0dfe79e3..7a757d9eb 100644 --- a/deployment/hetzner_cloud/README.md +++ b/deployment/hetzner_cloud/README.md @@ -15,7 +15,7 @@ ssh_authorized_keys: - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAkLGbzbG7KIGfkssKJBkc/0EVAzQ/8vjvVHzNdxhK8J yourname ``` -I made a (german) video to show it to you: +I made a (german) video to show it to you (video is older, cloudConfig.yaml differ): [![Video](https://img.youtube.com/vi/fORK3Bt3lPw/hqdefault.jpg)](https://www.youtube.com/watch?v=fORK3Bt3lPw) @@ -58,9 +58,8 @@ $ ssh -i /path/to/privKey gradido@gddhost.tld ### Disable password root login via ssh ```bash -sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.org -sudo sed -i -e '/^\(#\|\)PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config -sudo sed -i '$a AllowUsers gradido' /etc/ssh/sshd_config +sudo sed -i -e '/^\(#\|\)PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config.d/ssh-hardening.conf +sudo sed -i '$a AllowUsers gradido' /etc/ssh/sshd_config.d/ssh-hardening.conf sudo /etc/init.d/ssh restart ``` @@ -110,10 +109,10 @@ will remove it and ln ../bare_metal/nginx/conf.d ```bash cd ~/gradido/deployment/hetzner_cloud -sudo ./install.sh release-2_2_0 +sudo ./install.sh release-2_7_4 ``` -I made a (german) video to show it to you: +I made a (german) video to show it to you (video is older, output will differ): [![Video](https://img.youtube.com/vi/9h-55Si6bMk/hqdefault.jpg)](https://www.youtube.com/watch?v=9h-55Si6bMk) From fb38b314f4140bf22cee44e0deffc88d68bb61e2 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 13:02:09 +0100 Subject: [PATCH 10/19] fix bugs in install.sh --- deployment/hetzner_cloud/README.md | 4 +- deployment/hetzner_cloud/install.sh | 69 +++++++++++++---------------- 2 files changed, 33 insertions(+), 40 deletions(-) diff --git a/deployment/hetzner_cloud/README.md b/deployment/hetzner_cloud/README.md index 7a757d9eb..2d800c175 100644 --- a/deployment/hetzner_cloud/README.md +++ b/deployment/hetzner_cloud/README.md @@ -77,7 +77,7 @@ $ ssh -i /path/to/privKey gradido@gddhost.tld ### Install `Gradido` code ```bash cd ~ -git clone https://github.com/gradido/gradido.git +git clone https://github.com/gradido/gradido.git --branch latest ``` ### Adjust the values in `.env` @@ -109,7 +109,7 @@ will remove it and ln ../bare_metal/nginx/conf.d ```bash cd ~/gradido/deployment/hetzner_cloud -sudo ./install.sh release-2_7_4 +sudo ./install.sh latest ``` I made a (german) video to show it to you (video is older, output will differ): diff --git a/deployment/hetzner_cloud/install.sh b/deployment/hetzner_cloud/install.sh index 4ddcf44e4..a3fe924d8 100755 --- a/deployment/hetzner_cloud/install.sh +++ b/deployment/hetzner_cloud/install.sh @@ -4,7 +4,7 @@ set -euo pipefail log_error() { local message="$1" - echo -e "\e[31m$message\e[0m" >&3 # red in console + echo -e "\e[31m$message\e[0m" # red in console } # called always on error, log error really visible with ascii art in red on console and html @@ -46,49 +46,39 @@ echo 'Replace placeholder secrets in .env' # NOTE: all config values will be in process.env when starting # the services and will therefore take precedence over the .env if [ -f "$SCRIPT_PATH/.env" ]; then - ENV_FILE = $SCRIPT_PATH/.env + ENV_FILE="$SCRIPT_PATH/.env" # --- Secret Generators ------------------------------------------------------- gen_jwt_secret() { - # 32 Character, URL-safe: A-Z a-z 0-9 _ - - tr -dc 'A-Za-z0-9_-' < /dev/urandom | head -c 32 + # 32 Character, URL-safe: A-Z a-z 0-9 _ - + tr -dc 'A-Za-z0-9_-' < /dev/urandom | head -c 32 2>/dev/null || true } gen_webhook_secret() { - # URL-safe, longer security (40 chars) - tr -dc 'A-Za-z0-9_-' < /dev/urandom | head -c 40 + # URL-safe, longer security (40 chars) + tr -dc 'A-Za-z0-9_-' < /dev/urandom | head -c 40 2>/dev/null || true } gen_binary_secret() { - local bytes="$1" - # Hex -> 2 chars pro byte - openssl rand -hex "$bytes" + local bytes="$1" + # Hex -> 2 chars pro byte + openssl rand -hex "$bytes" 2>/dev/null || true } # --- Mapping of Placeholder -> Function -------------------------------------- generate_secret_for() { case "$1" in - jwt_secret) - gen_jwt_secret - ;; - webhook_secret) - gen_webhook_secret - ;; - binary8_secret) - gen_binary_secret 8 - ;; - binary16_secret) - gen_binary_secret 16 - ;; - binary32_secret) - gen_binary_secret 32 - ;; - *) - echo "Unknown Placeholder: $1" >&2 - exit 1 - ;; + jwt_secret) gen_jwt_secret ;; + webhook_secret) gen_webhook_secret ;; + binary8_secret) gen_binary_secret 8 ;; + binary16_secret) gen_binary_secret 16;; + binary32_secret) gen_binary_secret 32;; + *) + echo "Unknown Placeholder: $1" >&2 + exit 1 + ;; esac } @@ -108,15 +98,17 @@ if [ -f "$SCRIPT_PATH/.env" ]; then cp "$ENV_FILE" "$TMP_FILE" for ph in "${placeholders[@]}"; do - # Secret generate - new_value="$(generate_secret_for "$ph")" - - # Only replace lines that do NOT start with # - sed -i "/^[[:space:]]*#/! s/$ph/$new_value/g" "$TMP_FILE" + # Iterate over all lines containing the placeholder + while grep -q "$ph" "$TMP_FILE"; do + new_value=$(generate_secret_for "$ph") + # Replace only the first occurrence per line + sed -i "0,/$ph/s//$new_value/" "$TMP_FILE" + done done # Write back mv "$TMP_FILE" "$ENV_FILE" + chown gradido:gradido "$ENV_FILE" fi # If install.sh will be called more than once @@ -236,9 +228,12 @@ sudo -u gradido bash <<'EOF' fi # Install yarn and pm2 npm i -g yarn pm2 - # start pm2 - pm2 startup EOF +# Load nvm +export NVM_DIR="/home/gradido/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" +# start pm2 +pm2 startup # Install logrotate envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $SCRIPT_PATH/logrotate/gradido.conf.template > $SCRIPT_PATH/logrotate/gradido.conf @@ -247,9 +242,7 @@ cp $SCRIPT_PATH/logrotate/gradido.conf /etc/logrotate.d/gradido.conf # create db user export DB_USER=gradido # create a new password only if it not already exist -if [ -z "${DB_PASSWORD}" ]; then - export DB_PASSWORD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 32; echo); -fi +: "${DB_PASSWORD:=$(tr -dc '_A-Za-z0-9' < /dev/urandom | head -c 32)}" # Check if DB_PASSWORD is still empty, then exit with an error if [ -z "${DB_PASSWORD}" ]; then From aa5838650988ba33081f6d9154c2341ce0f55354 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 13:14:02 +0100 Subject: [PATCH 11/19] remove old install script, fix bug in start.sh with tag as branch --- deployment/bare_metal/install.sh | 149 ------------------------------- deployment/bare_metal/start.sh | 2 +- 2 files changed, 1 insertion(+), 150 deletions(-) delete mode 100755 deployment/bare_metal/install.sh diff --git a/deployment/bare_metal/install.sh b/deployment/bare_metal/install.sh deleted file mode 100755 index 284e40576..000000000 --- a/deployment/bare_metal/install.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/bash - -# This install script requires the minimum requirements already installed. -# How to do this is described in detail in [setup.md](./setup.md) - -# Find current directory & configure paths -## For manualy use in terminal -## set -o allexport -## SCRIPT_DIR=$(pwd) -## PROJECT_ROOT=$SCRIPT_DIR/../.. -## set +o allexport -# Use here in script -set -o allexport -SCRIPT_PATH=$(realpath $0) -SCRIPT_DIR=$(dirname $SCRIPT_PATH) -PROJECT_ROOT=$SCRIPT_DIR/../.. -set +o allexport - -# Load .env or .env.dist if not present -# NOTE: all config values will be in process.env when starting -# the services and will therefore take precedence over the .env -if [ -f "$SCRIPT_DIR/.env" ]; then - set -o allexport - source $SCRIPT_DIR/.env - set +o allexport -else - set -o allexport - source $SCRIPT_DIR/.env.dist - set +o allexport -fi - -# Configure git -git config pull.ff only - -# Install mariadb -sudo apt-get install -y mariadb-server -sudo mysql_secure_installation -# Enter current password for root (enter for none): enter -# Switch to unix_socket authentication [Y/n] Y -# Change the root password? [Y/n] n -# Remove anonymous users? [Y/n] Y -# Disallow root login remotely? [Y/n] Y -# Remove test database and access to it? [Y/n] Y -# Reload privilege tables now? [Y/n] Y - -# Install nginx -sudo apt-get install -y nginx -sudo rm /etc/nginx/sites-enabled/default -sudo ln -s /home/gradido/gradido/deployment/bare_metal/nginx/sites-available/gradido.conf /etc/nginx/sites-available -# sudo ln -s /etc/nginx/sites-available/gradido.conf /etc/nginx/sites-enabled -sudo ln -s /home/gradido/gradido/deployment/bare_metal/nginx/sites-available/update-page.conf /etc/nginx/sites-available -sudo ln -s /home/gradido/gradido/deployment/bare_metal/nginx/common /etc/nginx/ -sudo rmdir /etc/nginx/conf.d -sudo ln -s /home/gradido/gradido/deployment/bare_metal/nginx/conf.d /etc/nginx/ - -# Allow nginx configuration and restart for gradido -#TODO generate file -sudo nano /etc/sudoers.d/gradido -> gradido ALL=(ALL) NOPASSWD: /etc/init.d/nginx start,/etc/init.d/nginx stop,/etc/init.d/nginx restart -sudo chmod a+rw /etc/nginx/sites-enabled - -# Install node 16.x -sudo apt-get install -y curl -curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash - -sudo apt-get install -y nodejs -sudo apt-get install -y build-essential - -# Install yarn -sudo apt-get install -y gnupg -curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - -echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list -sudo apt-get update -sudo apt-get install -y yarn - -# Install pm2 -sudo yarn global add pm2 -pm2 startup -> execute command output in shell - -# Install certbot -sudo apt-get install -y certbot -sudo apt-get install -y python3-certbot-nginx -sudo certbot -> Enter email address (used for urgent renewal and security notices) > e.g. support@supportmail.com -> Please read the Terms of Service at > Y -> Would you be willing, once your first certificate is successfully issued, to > N -> No names were found in your configuration files. Please enter in your domain > stage1.gradido.net -# Note: this will throw an error regarding not beeing able to identify the nginx corresponding -# config but produce the required certificate - thats perfectly fine this way -# Troubleshoot: to manually renew a certificate with running nginx use the following command: -# (this might be required once to properly have things setup for the cron to autorenew) -# sudo certbot --nginx -d example.com -d www.example.com -# Troubleshoot: to check ut if things working you can use -# sudo certbot renew --dry-run - -# Install logrotate -sudo apt-get install -y logrotate -envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $SCRIPT_DIR/logrotate/gradido.conf.template > $SCRIPT_DIR/logrotate/gradido.conf -sudo cp $SCRIPT_DIR/logrotate/gradido.conf.template /etc/logrotate.d/gradido.conf -sudo chown root:root /etc/logrotate.d/gradido.conf - -# Install mysql autobackup -sudo apt-get install -y automysqlbackup - -# Webhooks (optional) (for development) -sudo apt install -y webhook -# TODO generate -# put hook into github -# TODO adjust secret -# TODO adjust branch if needed -# https://stage1.gradido.net/hooks/github -envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $SCRIPT_DIR/webhook/hooks.json.template > ~/hooks.json - -webhook -hooks ~/hooks.json & -# or for debugging -# webhook -hooks ~/hooks.json -verbose - -# create db user -export DB_USER=gradido -export DB_PASSWORD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo); -sudo mysql < $PROJECT_ROOT/database/.env - -# Configure backend -export JWT_SECRET=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo); -envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/backend/.env.template > $PROJECT_ROOT/backend/.env - -# Configure frontend -envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/frontend/.env.template > $PROJECT_ROOT/frontend/.env - -# Configure admin -envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/admin/.env.template > $PROJECT_ROOT/admin/.env - -# Configure dht-node -envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/dht-node/.env.template > $PROJECT_ROOT/dht-node/.env - -# create cronjob to delete yarn output in /tmp -# crontab -e -# hourly job: 0 * * * * find /tmp -name "yarn--*" -cmin +60 -exec rm -r {} \; > /dev/null -# daily job: 0 4 * * * find /tmp -name "yarn--*" -ctime +1 -exec rm -r {} \; > /dev/null -# Start gradido -# Note: on first startup some errors will occur - nothing serious -./start.sh diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh index 194e879e6..4ba2229bb 100755 --- a/deployment/bare_metal/start.sh +++ b/deployment/bare_metal/start.sh @@ -184,7 +184,7 @@ cd $PROJECT_ROOT # TODO: this overfetches alot, but ensures we can use start.sh with tags git fetch --all git checkout $BRANCH_NAME -git pull +git pull origin $BRANCH_NAME git submodule update --init --recursive export BUILD_COMMIT="$(git rev-parse HEAD)" From b6417f9a545f47148f22802bd0319cd4e4f762dc Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 13:17:51 +0100 Subject: [PATCH 12/19] update release script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 80ffdf872..190857a34 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ ], "scripts": { "release": "bumpp -r", - "version": "auto-changelog -p --commit-limit 0 && git add CHANGELOG.md", + "postrelease": "git push origin :refs/tags/latest && git tag -f latest && git push origin latest", + "version": "auto-changelog -p --commit-limit 0 && git add CHANGELOG.md && git commit -m \"update changelog\" && git push", "installAll": "bun run install", "docker": "cross-env BUILD_COMMIT=$(git rev-parse HEAD) docker compose -f docker-compose.yml up", "docker:rebuild": "cross-env BUILD_COMMIT=$(git rev-parse HEAD) docker compose -f docker-compose.yml build", From dbad91015d3913108070328d94b62793bdc6e709 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 13:23:09 +0100 Subject: [PATCH 13/19] add validation info in .env.dist, update readme for release tag --- deployment/bare_metal/.env.dist | 1 + deployment/hetzner_cloud/README.md | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index e738feec1..8528b4df7 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -1,6 +1,7 @@ # Need to adjust! # Will be seen on login and from other communities if dht and federation modules are active COMMUNITY_NAME="Your community name" +# Description should have at least 10 characters COMMUNITY_DESCRIPTION="Short Description from your Community." # your domain name, without protocol (without https:// or http:// ) # domain name should be configured in your dns records to point to this server diff --git a/deployment/hetzner_cloud/README.md b/deployment/hetzner_cloud/README.md index 2d800c175..dbec1cf9b 100644 --- a/deployment/hetzner_cloud/README.md +++ b/deployment/hetzner_cloud/README.md @@ -75,9 +75,10 @@ $ ssh -i /path/to/privKey gradido@gddhost.tld ``` ### Install `Gradido` code +`latest` is a tag pointing on last stable release ```bash cd ~ -git clone https://github.com/gradido/gradido.git --branch latest +git clone https://github.com/gradido/gradido.git --branch latest --depth 1 ``` ### Adjust the values in `.env` @@ -102,7 +103,7 @@ nano .env # adjust values accordingly ``` -### Run `install.sh` with branch name +### Run `install.sh` with branch or tag name ***!!! Attention !!!*** Don't use this script if you have custom config in /etc/nginx/conf.d, because this script will remove it and ln ../bare_metal/nginx/conf.d From 87cb1473dddab6a163ede7749928aa853ef007c0 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 13:33:51 +0100 Subject: [PATCH 14/19] improve db error message, export db passwort correct --- database/migration/index.ts | 2 +- deployment/hetzner_cloud/install.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/database/migration/index.ts b/database/migration/index.ts index 2c84fb594..62d1f1107 100644 --- a/database/migration/index.ts +++ b/database/migration/index.ts @@ -25,7 +25,7 @@ const run = async (command: string) => { host: ${CONFIG.DB_HOST} port: ${CONFIG.DB_PORT} user: ${CONFIG.DB_USER} - password: ${CONFIG.DB_PASSWORD.slice(-2)} + password: last 2 character: ${CONFIG.DB_PASSWORD.slice(-2)} database: ${CONFIG.DB_DATABASE}`, ) } diff --git a/deployment/hetzner_cloud/install.sh b/deployment/hetzner_cloud/install.sh index a3fe924d8..dbea76381 100755 --- a/deployment/hetzner_cloud/install.sh +++ b/deployment/hetzner_cloud/install.sh @@ -249,6 +249,8 @@ if [ -z "${DB_PASSWORD}" ]; then echo "Error: Failed to generate DB_PASSWORD." exit 1 fi +export DB_PASSWORD + mysql < Date: Fri, 5 Dec 2025 13:35:06 +0100 Subject: [PATCH 15/19] move latest tag after version to have correct changelog.md in latest --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 190857a34..c00167ab8 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,8 @@ ], "scripts": { "release": "bumpp -r", - "postrelease": "git push origin :refs/tags/latest && git tag -f latest && git push origin latest", "version": "auto-changelog -p --commit-limit 0 && git add CHANGELOG.md && git commit -m \"update changelog\" && git push", + "postversion": "git push origin :refs/tags/latest && git tag -f latest && git push origin latest", "installAll": "bun run install", "docker": "cross-env BUILD_COMMIT=$(git rev-parse HEAD) docker compose -f docker-compose.yml up", "docker:rebuild": "cross-env BUILD_COMMIT=$(git rev-parse HEAD) docker compose -f docker-compose.yml build", From 5eed9b3bc1d3a1758a63ff61d6e231b45153152e Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 5 Dec 2025 13:47:26 +0100 Subject: [PATCH 16/19] add bun and turbo direct in install.sh, add redis and unzip direct in cloudConfig.yml --- deployment/hetzner_cloud/cloudConfig.yaml | 2 ++ deployment/hetzner_cloud/install.sh | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/deployment/hetzner_cloud/cloudConfig.yaml b/deployment/hetzner_cloud/cloudConfig.yaml index e6970cf9c..282b7b400 100644 --- a/deployment/hetzner_cloud/cloudConfig.yaml +++ b/deployment/hetzner_cloud/cloudConfig.yaml @@ -14,6 +14,7 @@ packages: - git - mariadb-server - nginx + - redis - curl - build-essential - gnupg @@ -22,6 +23,7 @@ packages: - logrotate - automysqlbackup - expect + - unzip package_update: true package_upgrade: true write_files: diff --git a/deployment/hetzner_cloud/install.sh b/deployment/hetzner_cloud/install.sh index dbea76381..71b4c1bbb 100755 --- a/deployment/hetzner_cloud/install.sh +++ b/deployment/hetzner_cloud/install.sh @@ -226,9 +226,27 @@ sudo -u gradido bash <<'EOF' if ! nvm ls $NODE_VERSION >/dev/null 2>&1; then nvm install $NODE_VERSION fi - # Install yarn and pm2 - npm i -g yarn pm2 + + BUN_VERSION_FILE="$PROJECT_ROOT/.bun-version" + if [ ! -f "$BUN_VERSION_FILE" ]; then + echo ".bun-version file not found at: $BUN_VERSION_FILE" + exit 1 + fi + BUN_VERSION="$(cat "$BUN_VERSION_FILE" | tr -d '[:space:]')" + echo "'bun' v$BUN_VERSION will be installed now!" + curl -fsSL https://bun.com/install | bash -s "bun-v${BUN_VERSION}" + + # Load bun + export BUN_INSTALL="$HOME/.bun" + export PATH="$BUN_INSTALL/bin:$PATH" + + # Install pm2 and turbo + bun add -g pm2 turbo EOF +# Load bun +export BUN_INSTALL="$HOME/.bun" +export PATH="$BUN_INSTALL/bin:$PATH" + # Load nvm export NVM_DIR="/home/gradido/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" From 26d82214268e0703a96b41df8ebf7225ad50cc83 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sat, 6 Dec 2025 09:37:18 +0100 Subject: [PATCH 17/19] update readme --- deployment/hetzner_cloud/README.md | 44 ++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/deployment/hetzner_cloud/README.md b/deployment/hetzner_cloud/README.md index dbec1cf9b..89786c07b 100644 --- a/deployment/hetzner_cloud/README.md +++ b/deployment/hetzner_cloud/README.md @@ -1,6 +1,15 @@ # Migration [Migration from 2.2.0 to 2.2.1](migration/2_2_0-2_2_1/README.md) +# Key Pair +It is recommended to create a new ssh key pair for your gradido server. +You can create it with this command: +```bash +ssh-keygen -t ed25519 -C "your_email@example.com" +``` + +**Reason**: We recommend `ed25519` because it provides strong security with smaller key sizes, faster performance, and resistance to known attacks, making it more secure and efficient than traditional RSA keys. + # Setup on Hetzner Cloud Server Suggested OS: Debian 12 @@ -23,14 +32,7 @@ I made a (german) video to show it to you (video is older, cloudConfig.yaml diff ### setup your domain pointing on server ip address ### login to your new server as root ```bash -ssh -i /path/to/privKey root@gddhost.tld -``` - -### Change default shell - -```bash -chsh -s /bin/bash -chsh -s /bin/bash gradido +ssh -i ~/.ssh/id_ed25519 root@gddhost.tld ``` ### Set password for user `gradido` @@ -51,7 +53,7 @@ su gradido If you logout from the server you can test authentication: ```bash -$ ssh -i /path/to/privKey gradido@gddhost.tld +$ ssh -i ~/.ssh/id_ed25519 gradido@gddhost.tld # This should log you in and allow you to use sudo commands, which will require the user's password ``` @@ -68,9 +70,9 @@ sudo /etc/init.d/ssh restart ```bash $ ssh gradido@gddhost.tld # Will result in in either a passphrase request for your key or the message 'Permission denied (publickey)' -$ ssh -i /path/to/privKey root@gddhost.tld +$ ssh -i ~/.ssh/id_ed25519 root@gddhost.tld # Will result in 'Permission denied (publickey)' -$ ssh -i /path/to/privKey gradido@gddhost.tld +$ ssh -i ~/.ssh/id_ed25519 gradido@gddhost.tld # Will succeed after entering the correct keys passphrase (if any) ``` @@ -99,8 +101,22 @@ All your following installations in `install.sh` will fail!* cd ~/gradido/deployment/bare_metal cp .env.dist .env nano .env +``` -# adjust values accordingly +For a minimal setup you need at least to change this values: +```env +COMMUNITY_NAME="Your community name" +COMMUNITY_DESCRIPTION="Short Description from your Community." +# your domain name, without protocol (without https:// or http:// ) +# domain name should be configured in your dns records to point to this server +# hetzner_cloud/install.sh will be acquire a SSL-certificate via letsencrypt for this domain +COMMUNITY_HOST=gddhost.tld + +# setup email account for sending gradido system messages to users +EMAIL_USERNAME=peter@lustig.de +EMAIL_SENDER=peter@lustig.de +EMAIL_PASSWORD=1234 +EMAIL_SMTP_HOST=smtp.lustig.de ``` ### Run `install.sh` with branch or tag name @@ -133,3 +149,7 @@ sudo mysql -D gradido_community -e "insert into user_roles(user_id, role) values I made a (german) video to show it to you: [![Video](https://img.youtube.com/vi/xVQ5t4MnLrE/hqdefault.jpg)](https://www.youtube.com/watch?v=xVQ5t4MnLrE) + +### But it isn't working + +If it isn't working you can write us: [support@gradido.net](mailto:support@gradido.net) From 30b03b24a2d171cab48c12916667718c84051206 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sat, 6 Dec 2025 10:44:52 +0100 Subject: [PATCH 18/19] fix bugs --- deployment/bare_metal/.env.dist | 3 +- deployment/bare_metal/install-missing-deps.sh | 11 ++--- deployment/bare_metal/start.sh | 5 +++ deployment/hetzner_cloud/install.sh | 41 ++++++++----------- 4 files changed, 31 insertions(+), 29 deletions(-) diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index 8528b4df7..722a72c88 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -50,7 +50,7 @@ DEPLOY_SEED_DATA=false # test email # if true all email will be send to EMAIL_TEST_RECEIVER instead of email address of user EMAIL_TEST_MODUS=false -EMAIL_TEST_RECEIVER=test_team@gddhost.tld +EMAIL_TEST_RECEIVER=test_team@gradido.net # webhook for auto update on github repository changes WEBHOOK_GITHUB_BRANCH=master @@ -103,6 +103,7 @@ META_AUTHOR="Bernd Hückstädt - Gradido-Akademie" # externe gradido services GDT_ACTIVE=false +GDT_API_URL=https://gdt.gradido.net # DLT-Connector (still in develop) # verify transaction additional via gradido blockchain diff --git a/deployment/bare_metal/install-missing-deps.sh b/deployment/bare_metal/install-missing-deps.sh index 1eb2d616e..9b513c026 100644 --- a/deployment/bare_metal/install-missing-deps.sh +++ b/deployment/bare_metal/install-missing-deps.sh @@ -1,10 +1,11 @@ #!/bin/bash +# source profile so PATH/NVM/BUN werden gesetzt (safe for non-login) +if [ -f /home/gradido/.profile ]; then + . /home/gradido/.profile +fi # Ensure required tools are installed -# make sure correct node version is installed -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" if ! command -v nvm > /dev/null then echo "'nvm' is missing, will be installed now!" @@ -14,7 +15,7 @@ install_nvm() { nvm install nvm use nvm alias default - npm i -g yarn pm2 + npm i -g pm2 turbo pm2 startup } nvm use || install_nvm @@ -52,7 +53,7 @@ fi if ! command -v turbo > /dev/null then echo "'turbo' is missing, will be installed now!" - bun install --global turbo + npm i -g turbo fi # rust and grass diff --git a/deployment/bare_metal/start.sh b/deployment/bare_metal/start.sh index 4ba2229bb..dc237bc4b 100755 --- a/deployment/bare_metal/start.sh +++ b/deployment/bare_metal/start.sh @@ -2,6 +2,11 @@ # stop if something fails set -euo pipefail +# source profile so PATH/NVM/BUN werden gesetzt (safe for non-login) +if [ -f /home/gradido/.profile ]; then + . /home/gradido/.profile +fi + # check for parameter FAST_MODE=false POSITIONAL_ARGS=() diff --git a/deployment/hetzner_cloud/install.sh b/deployment/hetzner_cloud/install.sh index 71b4c1bbb..fd0996c19 100755 --- a/deployment/hetzner_cloud/install.sh +++ b/deployment/hetzner_cloud/install.sh @@ -210,11 +210,17 @@ sudo systemctl daemon-reload # setup https with certbot certbot certonly --nginx --non-interactive --agree-tos --domains $COMMUNITY_HOST --email $COMMUNITY_SUPPORT_MAIL +export NVM_DIR="/home/gradido/.nvm" +BUN_VERSION_FILE="$PROJECT_ROOT/.bun-version" +if [ ! -f "$BUN_VERSION_FILE" ]; then + echo ".bun-version file not found at: $BUN_VERSION_FILE" + exit 1 +fi +export BUN_VERSION="$(cat "$BUN_VERSION_FILE" | tr -d '[:space:]')" +export BUN_INSTALL="/home/gradido/.bun" + # run as gradido user (until EOF) -sudo -u gradido bash <<'EOF' - export NVM_DIR="/home/gradido/.nvm" - NODE_VERSION="v18.20.7" - export NVM_DIR +sudo -u gradido bash </dev/null 2>&1; then - nvm install $NODE_VERSION + if ! nvm ls >/dev/null 2>&1; then + nvm install fi - - BUN_VERSION_FILE="$PROJECT_ROOT/.bun-version" - if [ ! -f "$BUN_VERSION_FILE" ]; then - echo ".bun-version file not found at: $BUN_VERSION_FILE" - exit 1 - fi - BUN_VERSION="$(cat "$BUN_VERSION_FILE" | tr -d '[:space:]')" - echo "'bun' v$BUN_VERSION will be installed now!" - curl -fsSL https://bun.com/install | bash -s "bun-v${BUN_VERSION}" - - # Load bun - export BUN_INSTALL="$HOME/.bun" - export PATH="$BUN_INSTALL/bin:$PATH" - # Install pm2 and turbo - bun add -g pm2 turbo + npm i -g pm2 turbo + + echo "'bun' v$BUN_VERSION will be installed now!" + curl -fsSL https://bun.com/install | bash -s "bun-v${BUN_VERSION}" EOF + # Load bun -export BUN_INSTALL="$HOME/.bun" +export BUN_INSTALL="/home/gradido/.bun" export PATH="$BUN_INSTALL/bin:$PATH" # Load nvm @@ -302,5 +298,4 @@ chown -R gradido:gradido $PROJECT_ROOT sudo -u gradido crontab < $LOCAL_SCRIPT_DIR/crontabs.txt # Start gradido -# Note: on first startup some errors will occur - nothing serious sudo -u gradido $SCRIPT_PATH/start.sh $1 \ No newline at end of file From a3f46fa0115493ab8502f69b000d919820e9abfe Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Sat, 6 Dec 2025 11:01:47 +0100 Subject: [PATCH 19/19] add error description --- deployment/hetzner_cloud/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/deployment/hetzner_cloud/README.md b/deployment/hetzner_cloud/README.md index 89786c07b..2002a0b19 100644 --- a/deployment/hetzner_cloud/README.md +++ b/deployment/hetzner_cloud/README.md @@ -150,6 +150,15 @@ I made a (german) video to show it to you: [![Video](https://img.youtube.com/vi/xVQ5t4MnLrE/hqdefault.jpg)](https://www.youtube.com/watch?v=xVQ5t4MnLrE) +### Troubleshooting + +If after some tests this error occur, right after `Requesting a certificate for your-domain.tld`, try again another day. Letsencrypt is rate limited: + +```bash +An unexpected error occurred: +AttributeError: can't set attribute +``` + ### But it isn't working If it isn't working you can write us: [support@gradido.net](mailto:support@gradido.net)