Merge branch 'community-scripts:main' into step-ca
This commit is contained in:
commit
0f787aacd8
@ -1,6 +0,0 @@
|
|||||||
_ ___ __ ___ __
|
|
||||||
| | / (_)____/ /_ / (_)____/ /_
|
|
||||||
| | /| / / / ___/ __ \/ / / ___/ __/
|
|
||||||
| |/ |/ / (__ ) / / / / (__ ) /_
|
|
||||||
|__/|__/_/____/_/ /_/_/_/____/\__/
|
|
||||||
|
|
||||||
11
ct/wger.sh
11
ct/wger.sh
@ -31,7 +31,7 @@ function update_script() {
|
|||||||
|
|
||||||
if check_for_gh_release "wger" "wger-project/wger"; then
|
if check_for_gh_release "wger" "wger-project/wger"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop apache2
|
systemctl stop redis-server nginx celery celery-beat wger
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
msg_info "Backing up Data"
|
msg_info "Backing up Data"
|
||||||
@ -45,6 +45,7 @@ function update_script() {
|
|||||||
cp -r /opt/wger_media_backup/. /opt/wger/media
|
cp -r /opt/wger_media_backup/. /opt/wger/media
|
||||||
cp /opt/wger_env_backup /opt/wger/.env
|
cp /opt/wger_env_backup /opt/wger/.env
|
||||||
rm -rf /opt/wger_media_backup /opt/wger_env_backup
|
rm -rf /opt/wger_media_backup /opt/wger_env_backup
|
||||||
|
|
||||||
msg_ok "Restored Data"
|
msg_ok "Restored Data"
|
||||||
|
|
||||||
msg_info "Updating wger"
|
msg_info "Updating wger"
|
||||||
@ -56,9 +57,9 @@ function update_script() {
|
|||||||
$STD uv run python manage.py collectstatic --no-input
|
$STD uv run python manage.py collectstatic --no-input
|
||||||
msg_ok "Updated wger"
|
msg_ok "Updated wger"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Services"
|
||||||
systemctl start apache2
|
systemctl start redis-server nginx celery celery-beat wger
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Services"
|
||||||
msg_ok "Updated Successfully"
|
msg_ok "Updated Successfully"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
@ -71,4 +72,4 @@ description
|
|||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
|
||||||
|
|||||||
@ -1,76 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: Dunky13
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/cmintey/wishlist
|
|
||||||
|
|
||||||
APP="Wishlist"
|
|
||||||
var_tags="${var_tags:-sharing}"
|
|
||||||
var_cpu="${var_cpu:-2}"
|
|
||||||
var_ram="${var_ram:-2048}"
|
|
||||||
var_disk="${var_disk:-5}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-13}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
function update_script() {
|
|
||||||
header_info
|
|
||||||
check_container_storage
|
|
||||||
check_container_resources
|
|
||||||
if [[ ! -d /opt/wishlist ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "wishlist" "cmintey/wishlist"; then
|
|
||||||
NODE_VERSION="24" NODE_MODULE="pnpm" setup_nodejs
|
|
||||||
|
|
||||||
msg_info "Stopping Service"
|
|
||||||
systemctl stop wishlist
|
|
||||||
msg_ok "Stopped Service"
|
|
||||||
|
|
||||||
mkdir -p /opt/wishlist-backup
|
|
||||||
cp /opt/wishlist/.env /opt/wishlist-backup/.env
|
|
||||||
cp -a /opt/wishlist/uploads /opt/wishlist-backup
|
|
||||||
cp -a /opt/wishlist/data /opt/wishlist-backup
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "wishlist" "cmintey/wishlist" "tarball"
|
|
||||||
LATEST_APP_VERSION=$(get_latest_github_release "cmintey/wishlist" false)
|
|
||||||
|
|
||||||
msg_info "Updating Wishlist"
|
|
||||||
cd /opt/wishlist
|
|
||||||
$STD pnpm install
|
|
||||||
$STD pnpm svelte-kit sync
|
|
||||||
$STD pnpm prisma generate
|
|
||||||
sed -i 's|/usr/src/app/|/opt/wishlist/|g' $(grep -rl '/usr/src/app/' /opt/wishlist)
|
|
||||||
export VERSION="${LATEST_APP_VERSION}"
|
|
||||||
export SHA="${LATEST_APP_VERSION}"
|
|
||||||
$STD pnpm run build
|
|
||||||
$STD pnpm prune --prod
|
|
||||||
chmod +x /opt/wishlist/entrypoint.sh
|
|
||||||
cp /opt/wishlist-backup/.env /opt/wishlist/.env
|
|
||||||
cp -a /opt/wishlist-backup/uploads /opt/wishlist
|
|
||||||
cp -a /opt/wishlist-backup/data /opt/wishlist
|
|
||||||
rm -rf /opt/wishlist-backup
|
|
||||||
msg_ok "Updated Wishlist"
|
|
||||||
msg_info "Starting Service"
|
|
||||||
systemctl start wishlist
|
|
||||||
msg_ok "Started Service"
|
|
||||||
msg_ok "Updated successfully!"
|
|
||||||
fi
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
start
|
|
||||||
build_container
|
|
||||||
description
|
|
||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3280${CL}"
|
|
||||||
@ -1,72 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: StellaeAlis
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/writefreely/writefreely
|
|
||||||
|
|
||||||
# App Default Values
|
|
||||||
APP="WriteFreely"
|
|
||||||
var_tags="${var_tags:-writing}"
|
|
||||||
var_cpu="${var_cpu:-2}"
|
|
||||||
var_ram="${var_ram:-1024}"
|
|
||||||
var_disk="${var_disk:-4}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-13}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
|
|
||||||
function update_script() {
|
|
||||||
header_info
|
|
||||||
check_container_storage
|
|
||||||
check_container_resources
|
|
||||||
|
|
||||||
if [[ ! -d /opt/writefreely ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "writefreely" "writefreely/writefreely"; then
|
|
||||||
msg_info "Stopping Services"
|
|
||||||
systemctl stop writefreely
|
|
||||||
msg_ok "Stopped Services"
|
|
||||||
|
|
||||||
msg_info "Creating Backup"
|
|
||||||
mkdir -p /tmp/writefreely_backup
|
|
||||||
cp /opt/writefreely/keys /tmp/writefreely_backup/ 2>/dev/null
|
|
||||||
cp /opt/writefreely/config.ini /tmp/writefreely_backup/ 2>/dev/null
|
|
||||||
msg_ok "Created Backup"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "writefreely" "writefreely/writefreely" "prebuild" "latest" "/opt/writefreely" "writefreely_*_linux_amd64.tar.gz"
|
|
||||||
|
|
||||||
msg_info "Restoring Data"
|
|
||||||
cp /tmp/writefreely_backup/config.ini /opt/writefreely/ 2>/dev/null
|
|
||||||
cp /tmp/writefreely_backup/keys/* /opt/writefreely/keys/ 2>/dev/null
|
|
||||||
rm -rf /tmp/writefreely_backup
|
|
||||||
msg_ok "Restored Data"
|
|
||||||
|
|
||||||
msg_info "Running Post-Update Tasks"
|
|
||||||
cd /opt/writefreely
|
|
||||||
$STD ./writefreely db migrate
|
|
||||||
msg_ok "Ran Post-Update Tasks"
|
|
||||||
|
|
||||||
msg_info "Starting Services"
|
|
||||||
systemctl start writefreely
|
|
||||||
msg_ok "Started Services"
|
|
||||||
msg_ok "Updated successfully!"
|
|
||||||
fi
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
start
|
|
||||||
build_container
|
|
||||||
description
|
|
||||||
|
|
||||||
msg_ok "Completed successfully!\n"
|
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"generated": "2026-02-04T07:03:37Z",
|
"generated": "2026-02-04T13:17:54Z",
|
||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"slug": "affine",
|
"slug": "affine",
|
||||||
@ -99,13 +99,6 @@
|
|||||||
"pinned": true,
|
"pinned": true,
|
||||||
"date": "2026-01-28T15:08:23Z"
|
"date": "2026-01-28T15:08:23Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"slug": "piler",
|
|
||||||
"repo": "jsuto/piler",
|
|
||||||
"version": "piler-1.4.8",
|
|
||||||
"pinned": false,
|
|
||||||
"date": "2025-09-24T06:51:38Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"slug": "pixelfed",
|
"slug": "pixelfed",
|
||||||
"repo": "pixelfed/pixelfed",
|
"repo": "pixelfed/pixelfed",
|
||||||
@ -135,18 +128,11 @@
|
|||||||
"date": "2026-01-21T19:07:21Z"
|
"date": "2026-01-21T19:07:21Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "wishlist",
|
"slug": "wger",
|
||||||
"repo": "cmintey/wishlist",
|
"repo": "wger-project/wger",
|
||||||
"version": "v0.59.0",
|
"version": "2.4",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-01-19T16:42:14Z"
|
"date": "2026-01-18T12:12:02Z"
|
||||||
},
|
|
||||||
{
|
|
||||||
"slug": "writefreely",
|
|
||||||
"repo": "writefreely/writefreely",
|
|
||||||
"version": "v0.16.0",
|
|
||||||
"pinned": false,
|
|
||||||
"date": "2025-08-29T19:30:02Z"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"interface_port": 9000,
|
"interface_port": 9000,
|
||||||
"documentation": "https://nginxui.com/guide/",
|
"documentation": "https://nginxui.com/guide/",
|
||||||
"website": "https://nginxui.com",
|
"website": "https://nginxui.com",
|
||||||
"logo": "https://raw.githubusercontent.com/0xJacky/nginx-ui/master/app/public/logo.png",
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/nginx-ui.webp",
|
||||||
"config_path": "/usr/local/etc/nginx-ui/app.ini",
|
"config_path": "/usr/local/etc/nginx-ui/app.ini",
|
||||||
"description": "Nginx UI is a comprehensive web-based interface designed to simplify the management and configuration of Nginx servers. It provides features like online statistics, ChatGPT-powered config assistant, automatic Let's Encrypt certificates, and config file editing with syntax highlighting.",
|
"description": "Nginx UI is a comprehensive web-based interface designed to simplify the management and configuration of Nginx servers. It provides features like online statistics, ChatGPT-powered config assistant, automatic Let's Encrypt certificates, and config file editing with syntax highlighting.",
|
||||||
"install_methods": [
|
"install_methods": [
|
||||||
@ -32,10 +32,6 @@
|
|||||||
"password": null
|
"password": null
|
||||||
},
|
},
|
||||||
"notes": [
|
"notes": [
|
||||||
{
|
|
||||||
"text": "Create your admin account on first login via the web interface.",
|
|
||||||
"type": "info"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"text": "Nginx runs on ports 80/443, Nginx UI management interface on port 9000.",
|
"text": "Nginx runs on ports 80/443, Nginx UI management interface on port 9000.",
|
||||||
"type": "info"
|
"type": "info"
|
||||||
|
|||||||
@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Piler",
|
|
||||||
"slug": "piler",
|
|
||||||
"categories": [
|
|
||||||
7
|
|
||||||
],
|
|
||||||
"date_created": "2025-12-15",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 80,
|
|
||||||
"documentation": "https://www.mailpiler.org/",
|
|
||||||
"config_path": "",
|
|
||||||
"website": "https://www.mailpiler.org/",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/piler.webp",
|
|
||||||
"description": "Piler is a feature rich open source email archiving solution with support for legal hold, deduplication, full text search, and many more features.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/piler.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 4,
|
|
||||||
"ram": 4096,
|
|
||||||
"hdd": 20,
|
|
||||||
"os": "Debian",
|
|
||||||
"version": "12"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": null,
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": []
|
|
||||||
}
|
|
||||||
40
frontend/public/json/wger.json
Normal file
40
frontend/public/json/wger.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "wger",
|
||||||
|
"slug": "wger",
|
||||||
|
"categories": [
|
||||||
|
24
|
||||||
|
],
|
||||||
|
"date_created": "2025-02-24",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"interface_port": 3000,
|
||||||
|
"documentation": "https://wger.readthedocs.io/en/latest/index.html",
|
||||||
|
"website": "https://wger.de",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/wger.webp",
|
||||||
|
"config_path": "/opt/wger/wger.env",
|
||||||
|
"description": "wger (ˈvɛɡɐ) Workout Manager is a free, open source web application that helps you manage your personal workouts, weight and diet plans and can also be used as a simple gym management utility. It offers a REST API as well, for easy integration with other projects and tools.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/wger.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 2,
|
||||||
|
"ram": 2048,
|
||||||
|
"hdd": 8,
|
||||||
|
"os": "debian",
|
||||||
|
"version": "13"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": "admin",
|
||||||
|
"password": "adminadmin"
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"text": "This LXC also runs Celery and Redis to synchronize workouts and ingredients",
|
||||||
|
"type": "info"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Wishlist",
|
|
||||||
"slug": "wishlist",
|
|
||||||
"categories": [
|
|
||||||
0
|
|
||||||
],
|
|
||||||
"date_created": "2025-12-29",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 3280,
|
|
||||||
"documentation": "https://github.com/cmintey/wishlist/blob/main/README.md#getting-started",
|
|
||||||
"config_path": "/opt/wishlist/.env",
|
|
||||||
"website": "https://github.com/cmintey/wishlist",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/cmintey-wishlist.webp",
|
|
||||||
"description": "Wishlist is a self-hosted wishlist application that you can share with your friends and family. You no longer have to wonder what to get your family for the holidays, simply check their wishlist and claim any available item!",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/wishlist.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 2,
|
|
||||||
"ram": 2048,
|
|
||||||
"hdd": 5,
|
|
||||||
"os": "Debian",
|
|
||||||
"version": "13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": null,
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": []
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "WriteFreely",
|
|
||||||
"slug": "writefreely",
|
|
||||||
"categories": [
|
|
||||||
12
|
|
||||||
],
|
|
||||||
"date_created": "2026-01-25",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 80,
|
|
||||||
"documentation": "https://writefreely.org/docs",
|
|
||||||
"config_path": "/opt/writefreely/config.ini",
|
|
||||||
"website": "https://writefreely.org/",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/writefreely-light.webp",
|
|
||||||
"description": "WriteFreely is free and open source software for easily publishing writing on the web with support for the ActivityPub protocol. Use it to start a personal blog — or an entire community.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/writefreely.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 2,
|
|
||||||
"ram": 1024,
|
|
||||||
"hdd": 4,
|
|
||||||
"os": "Debian",
|
|
||||||
"version": "13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": null,
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": [
|
|
||||||
{
|
|
||||||
"text": "After installation execute `./writefreely user create --admin username:password` in the `/opt/writefreely` directory to create your user.",
|
|
||||||
"type": "info"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -29,13 +29,21 @@ $STD apt install -y \
|
|||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
PG_VERSION="16" setup_postgresql
|
PG_VERSION="16" setup_postgresql
|
||||||
PG_DB_NAME="discourse" PG_DB_USER="discourse" setup_postgresql_db
|
|
||||||
NODE_VERSION="22" setup_nodejs
|
NODE_VERSION="22" setup_nodejs
|
||||||
RUBY_VERSION="3.3" setup_ruby
|
RUBY_VERSION="3.3.6" setup_ruby
|
||||||
|
|
||||||
|
msg_info "Configuring PostgreSQL for Discourse"
|
||||||
|
DISCOURSE_DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
|
||||||
|
# Configure pg_hba.conf for md5 authentication
|
||||||
|
PG_HBA="/etc/postgresql/16/main/pg_hba.conf"
|
||||||
|
sed -i 's/^local\s\+all\s\+all\s\+peer$/local all all md5/' "$PG_HBA"
|
||||||
|
$STD systemctl restart postgresql
|
||||||
|
# Create user with CREATEDB permission - Rails will create the database
|
||||||
|
$STD sudo -u postgres psql -c "CREATE ROLE discourse WITH LOGIN PASSWORD '$DISCOURSE_DB_PASS' CREATEDB;"
|
||||||
|
msg_ok "Configured PostgreSQL for Discourse"
|
||||||
|
|
||||||
msg_info "Configuring Discourse"
|
msg_info "Configuring Discourse"
|
||||||
DISCOURSE_SECRET_KEY=$(openssl rand -hex 32)
|
DISCOURSE_SECRET_KEY=$(openssl rand -hex 64)
|
||||||
DISCOURSE_DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)
|
|
||||||
|
|
||||||
git clone --depth 1 https://github.com/discourse/discourse.git /opt/discourse
|
git clone --depth 1 https://github.com/discourse/discourse.git /opt/discourse
|
||||||
cd /opt/discourse
|
cd /opt/discourse
|
||||||
@ -45,7 +53,7 @@ RAILS_ENV=production
|
|||||||
RAILS_LOG_TO_STDOUT=true
|
RAILS_LOG_TO_STDOUT=true
|
||||||
RAILS_SERVE_STATIC_FILES=true
|
RAILS_SERVE_STATIC_FILES=true
|
||||||
SECRET_KEY_BASE=${DISCOURSE_SECRET_KEY}
|
SECRET_KEY_BASE=${DISCOURSE_SECRET_KEY}
|
||||||
DISCOURSE_DB_HOST=localhost
|
DISCOURSE_DB_HOST=/var/run/postgresql
|
||||||
DISCOURSE_DB_PORT=5432
|
DISCOURSE_DB_PORT=5432
|
||||||
DISCOURSE_DB_NAME=discourse
|
DISCOURSE_DB_NAME=discourse
|
||||||
DISCOURSE_DB_USERNAME=discourse
|
DISCOURSE_DB_USERNAME=discourse
|
||||||
@ -64,26 +72,42 @@ chmod 755 /opt/discourse
|
|||||||
msg_ok "Configured Discourse"
|
msg_ok "Configured Discourse"
|
||||||
|
|
||||||
msg_info "Installing Discourse Dependencies"
|
msg_info "Installing Discourse Dependencies"
|
||||||
|
$STD systemctl enable --now redis-server
|
||||||
cd /opt/discourse
|
cd /opt/discourse
|
||||||
$STD bundle install --deployment --without test development
|
export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
|
||||||
$STD yarn install
|
eval "$(rbenv init - bash)" 2>/dev/null || true
|
||||||
|
export RAILS_ENV=production
|
||||||
|
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
|
||||||
|
$STD corepack enable
|
||||||
|
$STD bundle config set --local deployment true
|
||||||
|
$STD bundle config set --local without 'test development'
|
||||||
|
$STD bundle install
|
||||||
|
$STD pnpm install
|
||||||
msg_ok "Installed Discourse Dependencies"
|
msg_ok "Installed Discourse Dependencies"
|
||||||
|
|
||||||
msg_info "Building Discourse Assets"
|
|
||||||
cd /opt/discourse
|
|
||||||
$STD bundle exec rails assets:precompile
|
|
||||||
msg_ok "Built Discourse Assets"
|
|
||||||
|
|
||||||
msg_info "Setting Up Database"
|
msg_info "Setting Up Database"
|
||||||
cd /opt/discourse
|
cd /opt/discourse
|
||||||
|
export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
|
||||||
|
eval "$(rbenv init - bash)" 2>/dev/null || true
|
||||||
|
export RAILS_ENV=production
|
||||||
|
$STD bundle exec rails db:create
|
||||||
$STD bundle exec rails db:migrate
|
$STD bundle exec rails db:migrate
|
||||||
$STD systemctl enable --now redis-server
|
|
||||||
$STD systemctl enable --now postgresql
|
|
||||||
msg_ok "Set Up Database"
|
msg_ok "Set Up Database"
|
||||||
|
|
||||||
|
msg_info "Building Discourse Assets"
|
||||||
|
cd /opt/discourse
|
||||||
|
export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
|
||||||
|
eval "$(rbenv init - bash)" 2>/dev/null || true
|
||||||
|
export RAILS_ENV=production
|
||||||
|
$STD bundle exec rails assets:precompile
|
||||||
|
msg_ok "Built Discourse Assets"
|
||||||
|
|
||||||
msg_info "Creating Discourse Admin User"
|
msg_info "Creating Discourse Admin User"
|
||||||
cd /opt/discourse
|
cd /opt/discourse
|
||||||
$STD bundle exec rails runner -e production "User.create!(email: 'admin@local', username: 'admin', password: '${DISCOURSE_DB_PASS}', admin: true)" || true
|
export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
|
||||||
|
eval "$(rbenv init - bash)" 2>/dev/null || true
|
||||||
|
export RAILS_ENV=production
|
||||||
|
$STD bundle exec rails runner "User.create!(email: 'admin@local', username: 'admin', password: '${DISCOURSE_DB_PASS}', admin: true)" || true
|
||||||
msg_ok "Created Discourse Admin User"
|
msg_ok "Created Discourse Admin User"
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
|
|||||||
@ -14,18 +14,18 @@ network_check
|
|||||||
update_os
|
update_os
|
||||||
|
|
||||||
msg_info "Installing Dependencies"
|
msg_info "Installing Dependencies"
|
||||||
$STD apt-get install -y \
|
$STD apt install -y \
|
||||||
apache2 \
|
build-essential \
|
||||||
libapache2-mod-wsgi-py3 \
|
nginx \
|
||||||
|
redis-server \
|
||||||
libpq-dev
|
libpq-dev
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
import_local_ip
|
||||||
NODE_VERSION="22" NODE_MODULE="sass" setup_nodejs
|
NODE_VERSION="22" NODE_MODULE="sass" setup_nodejs
|
||||||
setup_uv
|
setup_uv
|
||||||
|
|
||||||
PG_VERSION="16" setup_postgresql
|
PG_VERSION="16" setup_postgresql
|
||||||
PG_DB_NAME="wger" PG_DB_USER="wger" setup_postgresql_db
|
PG_DB_NAME="wger" PG_DB_USER="wger" setup_postgresql_db
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "wger" "wger-project/wger" "tarball" "latest" "/opt/wger"
|
fetch_and_deploy_gh_release "wger" "wger-project/wger" "tarball" "latest" "/opt/wger"
|
||||||
|
|
||||||
msg_info "Setting up wger"
|
msg_info "Setting up wger"
|
||||||
@ -36,85 +36,147 @@ $STD corepack enable
|
|||||||
$STD npm install
|
$STD npm install
|
||||||
$STD npm run build:css:sass
|
$STD npm run build:css:sass
|
||||||
$STD uv venv
|
$STD uv venv
|
||||||
$STD uv pip install .
|
$STD uv pip install . --group docker
|
||||||
SECRET_KEY=$(openssl rand -base64 40)
|
SECRET_KEY=$(openssl rand -base64 40)
|
||||||
cat <<EOF >/opt/wger/.env
|
cat <<EOF >/opt/wger/.env
|
||||||
|
DJANGO_SETTINGS_MODULE=settings.main
|
||||||
|
PYTHONPATH=/opt/wger
|
||||||
|
|
||||||
DJANGO_DB_ENGINE=django.db.backends.postgresql
|
DJANGO_DB_ENGINE=django.db.backends.postgresql
|
||||||
DJANGO_DB_DATABASE=${PG_DB_NAME}
|
DJANGO_DB_DATABASE=${PG_DB_NAME}
|
||||||
DJANGO_DB_USER=${PG_DB_USER}
|
DJANGO_DB_USER=${PG_DB_USER}
|
||||||
DJANGO_DB_PASSWORD=${PG_DB_PASS}
|
DJANGO_DB_PASSWORD=${PG_DB_PASS}
|
||||||
DJANGO_DB_HOST=localhost
|
DJANGO_DB_HOST=localhost
|
||||||
DJANGO_DB_PORT=5432
|
DJANGO_DB_PORT=5432
|
||||||
|
DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}
|
||||||
|
|
||||||
DJANGO_MEDIA_ROOT=/opt/wger/media
|
DJANGO_MEDIA_ROOT=/opt/wger/media
|
||||||
DJANGO_STATIC_ROOT=/opt/wger/static
|
DJANGO_STATIC_ROOT=/opt/wger/static
|
||||||
|
DJANGO_STATIC_URL=/static/
|
||||||
|
|
||||||
|
ALLOWED_HOSTS=${LOCAL_IP},localhost,127.0.0.1
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://${LOCAL_IP}:3000
|
||||||
|
|
||||||
|
USE_X_FORWARDED_HOST=True
|
||||||
|
SECURE_PROXY_SSL_HEADER=HTTP_X_FORWARDED_PROTO,http
|
||||||
|
|
||||||
|
DJANGO_CACHE_BACKEND=django_redis.cache.RedisCache
|
||||||
|
DJANGO_CACHE_LOCATION=redis://127.0.0.1:6379/1
|
||||||
|
DJANGO_CACHE_TIMEOUT=300
|
||||||
|
DJANGO_CACHE_CLIENT_CLASS=django_redis.client.DefaultClient
|
||||||
|
AXES_CACHE_ALIAS=default
|
||||||
|
|
||||||
|
USE_CELERY=True
|
||||||
|
CELERY_BROKER=redis://127.0.0.1:6379/2
|
||||||
|
CELERY_BACKEND=redis://127.0.0.1:6379/2
|
||||||
|
|
||||||
|
SITE_URL=http://${LOCAL_IP}:3000
|
||||||
SECRET_KEY=${SECRET_KEY}
|
SECRET_KEY=${SECRET_KEY}
|
||||||
EOF
|
EOF
|
||||||
cat <<'WSGI' >/opt/wger/wsgi_wrapper.py
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
env_file = Path('/opt/wger/.env')
|
|
||||||
if env_file.exists():
|
|
||||||
for line in env_file.read_text().splitlines():
|
|
||||||
if line.strip() and not line.startswith('#') and '=' in line:
|
|
||||||
key, value = line.split('=', 1)
|
|
||||||
os.environ.setdefault(key.strip(), value.strip())
|
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.main')
|
|
||||||
|
|
||||||
from wger.wsgi import application
|
|
||||||
WSGI
|
|
||||||
set -a && source /opt/wger/.env && set +a
|
set -a && source /opt/wger/.env && set +a
|
||||||
export DJANGO_SETTINGS_MODULE=settings.main
|
$STD uv run wger bootstrap
|
||||||
$STD uv run python manage.py migrate
|
|
||||||
$STD uv run python manage.py loaddata languages
|
|
||||||
$STD uv run python manage.py loaddata gym_config
|
|
||||||
$STD uv run python manage.py loaddata groups
|
|
||||||
$STD uv run python manage.py loaddata site
|
|
||||||
$STD uv run python manage.py collectstatic --no-input
|
$STD uv run python manage.py collectstatic --no-input
|
||||||
cat <<EOF | uv run python manage.py shell
|
cat <<EOF | uv run python manage.py shell
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
UserModel = get_user_model()
|
User = get_user_model()
|
||||||
user = UserModel.objects.create_user('admin', email='admin@localhost', password='${PG_DB_PASS}')
|
|
||||||
|
user, created = User.objects.get_or_create(
|
||||||
|
username="admin",
|
||||||
|
defaults={"email": "admin@localhost"},
|
||||||
|
)
|
||||||
|
|
||||||
|
if created:
|
||||||
|
user.set_password("${PG_DB_PASS}")
|
||||||
user.is_superuser = True
|
user.is_superuser = True
|
||||||
user.is_staff = True
|
user.is_staff = True
|
||||||
user.save()
|
user.save()
|
||||||
EOF
|
EOF
|
||||||
msg_ok "Set up wger"
|
msg_ok "Set up wger"
|
||||||
|
msg_info "Creating Config and Services"
|
||||||
|
cat <<EOF >/etc/systemd/system/wger.service
|
||||||
|
[Unit]
|
||||||
|
Description=wger Gunicorn
|
||||||
|
After=network.target
|
||||||
|
|
||||||
msg_info "Creating Service"
|
[Service]
|
||||||
cat <<EOF >/etc/apache2/sites-available/wger.conf
|
User=root
|
||||||
<Directory /opt/wger>
|
WorkingDirectory=/opt/wger
|
||||||
<Files wsgi_wrapper.py>
|
EnvironmentFile=/opt/wger/.env
|
||||||
Require all granted
|
ExecStart=/opt/wger/.venv/bin/gunicorn \
|
||||||
</Files>
|
--bind 127.0.0.1:8000 \
|
||||||
</Directory>
|
--workers 3 \
|
||||||
|
--threads 2 \
|
||||||
|
--timeout 120 \
|
||||||
|
wger.wsgi:application
|
||||||
|
Restart=always
|
||||||
|
|
||||||
<VirtualHost *:80>
|
[Install]
|
||||||
WSGIApplicationGroup %{GLOBAL}
|
WantedBy=multi-user.target
|
||||||
WSGIDaemonProcess wger python-path=/opt/wger python-home=/opt/wger/.venv
|
|
||||||
WSGIProcessGroup wger
|
|
||||||
WSGIScriptAlias / /opt/wger/wsgi_wrapper.py
|
|
||||||
WSGIPassAuthorization On
|
|
||||||
|
|
||||||
Alias /static/ /opt/wger/static/
|
|
||||||
<Directory /opt/wger/static>
|
|
||||||
Require all granted
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
Alias /media/ /opt/wger/media/
|
|
||||||
<Directory /opt/wger/media>
|
|
||||||
Require all granted
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
ErrorLog /var/log/apache2/wger-error.log
|
|
||||||
CustomLog /var/log/apache2/wger-access.log combined
|
|
||||||
</VirtualHost>
|
|
||||||
EOF
|
EOF
|
||||||
$STD a2dissite 000-default.conf
|
cat <<EOF >/etc/systemd/system/celery.service
|
||||||
$STD a2ensite wger
|
[Unit]
|
||||||
systemctl restart apache2
|
Description=wger Celery Worker
|
||||||
msg_ok "Created Service"
|
After=network.target redis-server.service
|
||||||
|
Requires=redis-server.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
WorkingDirectory=/opt/wger
|
||||||
|
EnvironmentFile=/opt/wger/.env
|
||||||
|
ExecStart=/opt/wger/.venv/bin/celery -A wger worker -l info
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
mkdir -p /var/lib/wger/celery
|
||||||
|
chmod 700 /var/lib/wger/celery
|
||||||
|
cat <<EOF >/etc/systemd/system/celery-beat.service
|
||||||
|
[Unit]
|
||||||
|
Description=wger Celery Beat
|
||||||
|
After=network.target redis-server.service
|
||||||
|
Requires=redis-server.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
WorkingDirectory=/opt/wger
|
||||||
|
EnvironmentFile=/opt/wger/.env
|
||||||
|
ExecStart=/opt/wger/.venv/bin/celery -A wger beat -l info \
|
||||||
|
--schedule /var/lib/wger/celery/celerybeat-schedule
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
cat <<'EOF' >/etc/nginx/sites-available/wger
|
||||||
|
server {
|
||||||
|
listen 3000;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
client_max_body_size 20M;
|
||||||
|
|
||||||
|
location /static/ {
|
||||||
|
alias /opt/wger/static/;
|
||||||
|
expires 30d;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /media/ {
|
||||||
|
alias /opt/wger/media/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:8000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_redirect off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
$STD rm -f /etc/nginx/sites-enabled/default
|
||||||
|
$STD ln -sf /etc/nginx/sites-available/wger /etc/nginx/sites-enabled/wger
|
||||||
|
systemctl enable -q --now redis-server nginx wger celery celery-beat
|
||||||
|
systemctl restart nginx
|
||||||
|
msg_ok "Created Config and Services"
|
||||||
|
|
||||||
motd_ssh
|
motd_ssh
|
||||||
customize
|
customize
|
||||||
|
|||||||
@ -1,67 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: Dunky13
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/cmintey/wishlist
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Installing dependencies"
|
|
||||||
$STD apt install -y \
|
|
||||||
build-essential \
|
|
||||||
python3 \
|
|
||||||
openssl \
|
|
||||||
caddy
|
|
||||||
msg_ok "Installed dependencies"
|
|
||||||
|
|
||||||
NODE_VERSION="24" NODE_MODULE="pnpm" setup_nodejs
|
|
||||||
fetch_and_deploy_gh_release "wishlist" "cmintey/wishlist" "tarball"
|
|
||||||
LATEST_APP_VERSION=$(get_latest_github_release "cmintey/wishlist" false)
|
|
||||||
|
|
||||||
|
|
||||||
msg_info "Installing Wishlist"
|
|
||||||
cd /opt/wishlist
|
|
||||||
cp .env.example .env
|
|
||||||
sed -i "s|^ORIGIN=.*|ORIGIN=http://${LOCAL_IP}:3000|" /opt/wishlist/.env
|
|
||||||
echo "NODE_ENV=production" >>/opt/wishlist/.env
|
|
||||||
$STD pnpm install
|
|
||||||
$STD pnpm svelte-kit sync
|
|
||||||
$STD pnpm prisma generate
|
|
||||||
sed -i 's|/usr/src/app/|/opt/wishlist/|g' $(grep -rl '/usr/src/app/' /opt/wishlist)
|
|
||||||
export VERSION="v${LATEST_APP_VERSION}"
|
|
||||||
export SHA="v${LATEST_APP_VERSION}"
|
|
||||||
$STD pnpm run build
|
|
||||||
$STD pnpm prune --prod
|
|
||||||
chmod +x /opt/wishlist/entrypoint.sh
|
|
||||||
mkdir -p /opt/wishlist/uploads
|
|
||||||
mkdir -p /opt/wishlist/data
|
|
||||||
msg_ok "Installed Wishlist"
|
|
||||||
|
|
||||||
msg_info "Creating Service"
|
|
||||||
cat <<EOF >/etc/systemd/system/wishlist.service
|
|
||||||
[Unit]
|
|
||||||
Description=Wishlist Service
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
WorkingDirectory=/opt/wishlist
|
|
||||||
EnvironmentFile=/opt/wishlist/.env
|
|
||||||
ExecStart=/usr/bin/env sh -c './entrypoint.sh'
|
|
||||||
Restart=on-failure
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
systemctl enable -q --now wishlist
|
|
||||||
msg_ok "Created Service"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
cleanup_lxc
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: StellaeAlis
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/writefreely/writefreely
|
|
||||||
|
|
||||||
# Import Functions and Setup
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Installing Dependencies"
|
|
||||||
$STD apt install -y crudini
|
|
||||||
msg_ok "Installed Dependencies"
|
|
||||||
|
|
||||||
setup_mariadb
|
|
||||||
MARIADB_DB_NAME="writefreely" MARIADB_DB_USER="writefreely" setup_mariadb_db
|
|
||||||
|
|
||||||
get_lxc_ip
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "writefreely" "writefreely/writefreely" "prebuild" "latest" "/opt/writefreely" "writefreely_*_linux_amd64.tar.gz"
|
|
||||||
|
|
||||||
msg_info "Setting up WriteFreely"
|
|
||||||
cd /opt/writefreely
|
|
||||||
$STD ./writefreely config generate
|
|
||||||
$STD ./writefreely keys generate
|
|
||||||
msg_ok "Setup WriteFreely"
|
|
||||||
|
|
||||||
msg_info "Configuring WriteFreely"
|
|
||||||
$STD crudini --set config.ini server port 80
|
|
||||||
$STD crudini --set config.ini server bind $LOCAL_IP
|
|
||||||
$STD crudini --set config.ini database username $MARIADB_DB_USER
|
|
||||||
$STD crudini --set config.ini database password $MARIADB_DB_PASS
|
|
||||||
$STD crudini --set config.ini database database $MARIADB_DB_NAME
|
|
||||||
$STD crudini --set config.ini app host http://$LOCAL_IP:80
|
|
||||||
$STD ./writefreely db init
|
|
||||||
msg_ok "Configured WriteFreely"
|
|
||||||
|
|
||||||
msg_info "Creating Service"
|
|
||||||
cat <<EOF >/etc/systemd/system/writefreely.service
|
|
||||||
[Unit]
|
|
||||||
Description=WriteFreely Service
|
|
||||||
After=syslog.target network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
WorkingDirectory=/opt/writefreely
|
|
||||||
ExecStart=/opt/writefreely/writefreely
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
systemctl enable -q --now writefreely
|
|
||||||
msg_ok "Created Service"
|
|
||||||
|
|
||||||
msg_info "Cleaning up"
|
|
||||||
$STD rm ~/writefreely.creds
|
|
||||||
msg_ok "Cleaned up"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
|
|
||||||
cleanup_lxc
|
|
||||||
@ -35,10 +35,203 @@ set +u
|
|||||||
CLOUDINIT_DEFAULT_USER="${CLOUDINIT_DEFAULT_USER:-root}"
|
CLOUDINIT_DEFAULT_USER="${CLOUDINIT_DEFAULT_USER:-root}"
|
||||||
CLOUDINIT_DNS_SERVERS="${CLOUDINIT_DNS_SERVERS:-1.1.1.1 8.8.8.8}"
|
CLOUDINIT_DNS_SERVERS="${CLOUDINIT_DNS_SERVERS:-1.1.1.1 8.8.8.8}"
|
||||||
CLOUDINIT_SEARCH_DOMAIN="${CLOUDINIT_SEARCH_DOMAIN:-local}"
|
CLOUDINIT_SEARCH_DOMAIN="${CLOUDINIT_SEARCH_DOMAIN:-local}"
|
||||||
CLOUDINIT_SSH_KEYS="${CLOUDINIT_SSH_KEYS:-/root/.ssh/authorized_keys}"
|
CLOUDINIT_SSH_KEYS="${CLOUDINIT_SSH_KEYS:-}" # Empty by default - user must explicitly provide keys
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# SECTION 2: HELPER FUNCTIONS
|
# SECTION 2: SSH KEY DISCOVERY AND SELECTION
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# _ci_ssh_extract_keys_from_file - Extracts valid SSH public keys from a file
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
function _ci_ssh_extract_keys_from_file() {
|
||||||
|
local file="$1"
|
||||||
|
[[ -f "$file" && -r "$file" ]] || return 0
|
||||||
|
grep -E '^(ssh-(rsa|ed25519|dss|ecdsa)|ecdsa-sha2-)' "$file" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# _ci_ssh_discover_files - Scans standard paths for SSH keys
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
function _ci_ssh_discover_files() {
|
||||||
|
local -a cand=()
|
||||||
|
shopt -s nullglob
|
||||||
|
cand+=(/root/.ssh/authorized_keys /root/.ssh/authorized_keys2)
|
||||||
|
cand+=(/root/.ssh/*.pub)
|
||||||
|
cand+=(/etc/ssh/authorized_keys /etc/ssh/authorized_keys.d/*)
|
||||||
|
shopt -u nullglob
|
||||||
|
printf '%s\0' "${cand[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# _ci_ssh_build_choices - Builds whiptail checklist from SSH key files
|
||||||
|
#
|
||||||
|
# Sets: CI_SSH_CHOICES (array), CI_SSH_COUNT (int), CI_SSH_MAPFILE (path)
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
function _ci_ssh_build_choices() {
|
||||||
|
local -a files=("$@")
|
||||||
|
CI_SSH_CHOICES=()
|
||||||
|
CI_SSH_COUNT=0
|
||||||
|
CI_SSH_MAPFILE="$(mktemp)"
|
||||||
|
local id key typ fp cmt base
|
||||||
|
|
||||||
|
for f in "${files[@]}"; do
|
||||||
|
[[ -f "$f" && -r "$f" ]] || continue
|
||||||
|
base="$(basename -- "$f")"
|
||||||
|
# Skip known_hosts and private keys
|
||||||
|
case "$base" in
|
||||||
|
known_hosts | known_hosts.* | config) continue ;;
|
||||||
|
id_*) [[ "$f" != *.pub ]] && continue ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
while IFS= read -r key; do
|
||||||
|
[[ -n "$key" ]] || continue
|
||||||
|
|
||||||
|
typ=""
|
||||||
|
fp=""
|
||||||
|
cmt=""
|
||||||
|
read -r _typ _b64 _cmt <<<"$key"
|
||||||
|
typ="${_typ:-key}"
|
||||||
|
cmt="${_cmt:-}"
|
||||||
|
|
||||||
|
# Get fingerprint via ssh-keygen if available
|
||||||
|
if command -v ssh-keygen >/dev/null 2>&1; then
|
||||||
|
fp="$(printf '%s\n' "$key" | ssh-keygen -lf - 2>/dev/null | awk '{print $2}')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Shorten long comments
|
||||||
|
[[ ${#cmt} -gt 40 ]] && cmt="${cmt:0:37}..."
|
||||||
|
|
||||||
|
CI_SSH_COUNT=$((CI_SSH_COUNT + 1))
|
||||||
|
id="K${CI_SSH_COUNT}"
|
||||||
|
echo "${id}|${key}" >>"$CI_SSH_MAPFILE"
|
||||||
|
CI_SSH_CHOICES+=("$id" "[$typ] ${fp:+$fp }${cmt:+$cmt }— ${base}" "OFF")
|
||||||
|
done < <(_ci_ssh_extract_keys_from_file "$f")
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# configure_cloudinit_ssh_keys - Interactive SSH key selection for Cloud-Init
|
||||||
|
#
|
||||||
|
# Usage: configure_cloudinit_ssh_keys
|
||||||
|
# Sets: CLOUDINIT_SSH_KEYS (path to temporary file with selected keys)
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
function configure_cloudinit_ssh_keys() {
|
||||||
|
local backtitle="Proxmox VE Helper Scripts"
|
||||||
|
local ssh_key_mode
|
||||||
|
|
||||||
|
# Create temp file for selected keys
|
||||||
|
CLOUDINIT_SSH_KEYS_TEMP="$(mktemp)"
|
||||||
|
: >"$CLOUDINIT_SSH_KEYS_TEMP"
|
||||||
|
|
||||||
|
# Discover keys and build choices
|
||||||
|
IFS=$'\0' read -r -d '' -a _def_files < <(_ci_ssh_discover_files && printf '\0')
|
||||||
|
_ci_ssh_build_choices "${_def_files[@]}"
|
||||||
|
local default_key_count="$CI_SSH_COUNT"
|
||||||
|
|
||||||
|
if [[ "$default_key_count" -gt 0 ]]; then
|
||||||
|
ssh_key_mode=$(whiptail --backtitle "$backtitle" --title "SSH KEY SOURCE" --menu \
|
||||||
|
"Provision SSH keys for Cloud-Init VM:" 14 72 4 \
|
||||||
|
"found" "Select from detected keys (${default_key_count})" \
|
||||||
|
"manual" "Paste a single public key" \
|
||||||
|
"folder" "Scan another folder (path or glob)" \
|
||||||
|
"none" "No SSH keys (password auth only)" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
else
|
||||||
|
ssh_key_mode=$(whiptail --backtitle "$backtitle" --title "SSH KEY SOURCE" --menu \
|
||||||
|
"No host keys detected. Choose:" 12 72 3 \
|
||||||
|
"manual" "Paste a single public key" \
|
||||||
|
"folder" "Scan another folder (path or glob)" \
|
||||||
|
"none" "No SSH keys (password auth only)" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$ssh_key_mode" in
|
||||||
|
found)
|
||||||
|
# Show checklist with individual keys
|
||||||
|
local selection
|
||||||
|
selection=$(whiptail --backtitle "$backtitle" --title "SELECT SSH KEYS" \
|
||||||
|
--checklist "Select one or more keys to import:" 20 140 10 "${CI_SSH_CHOICES[@]}" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
|
||||||
|
for tag in $selection; do
|
||||||
|
tag="${tag%\"}"
|
||||||
|
tag="${tag#\"}"
|
||||||
|
local line
|
||||||
|
line=$(grep -E "^${tag}\|" "$CI_SSH_MAPFILE" | head -n1 | cut -d'|' -f2-)
|
||||||
|
[[ -n "$line" ]] && printf '%s\n' "$line" >>"$CLOUDINIT_SSH_KEYS_TEMP"
|
||||||
|
done
|
||||||
|
local imported
|
||||||
|
imported=$(wc -l <"$CLOUDINIT_SSH_KEYS_TEMP")
|
||||||
|
echo -e "${ROOTSSH:- 🔑 }${BOLD}${DGN}SSH Keys: ${BGN}${imported} key(s) selected${CL}"
|
||||||
|
;;
|
||||||
|
manual)
|
||||||
|
local pubkey
|
||||||
|
pubkey=$(whiptail --backtitle "$backtitle" --title "PASTE SSH PUBLIC KEY" \
|
||||||
|
--inputbox "Paste your SSH public key (ssh-rsa, ssh-ed25519, etc.):" 10 76 3>&1 1>&2 2>&3) || return 1
|
||||||
|
if [[ -n "$pubkey" ]]; then
|
||||||
|
echo "$pubkey" >"$CLOUDINIT_SSH_KEYS_TEMP"
|
||||||
|
echo -e "${ROOTSSH:- 🔑 }${BOLD}${DGN}SSH Keys: ${BGN}1 key added manually${CL}"
|
||||||
|
else
|
||||||
|
echo -e "${ROOTSSH:- 🔑 }${BOLD}${DGN}SSH Keys: ${BGN}none (empty input)${CL}"
|
||||||
|
CLOUDINIT_SSH_KEYS=""
|
||||||
|
rm -f "$CLOUDINIT_SSH_KEYS_TEMP" "$CI_SSH_MAPFILE" 2>/dev/null
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
folder)
|
||||||
|
local glob_path
|
||||||
|
glob_path=$(whiptail --backtitle "$backtitle" --title "SCAN FOLDER/GLOB" \
|
||||||
|
--inputbox "Enter a folder or glob to scan (e.g. /root/.ssh/*.pub):" 10 72 3>&1 1>&2 2>&3) || return 1
|
||||||
|
if [[ -n "$glob_path" ]]; then
|
||||||
|
shopt -s nullglob
|
||||||
|
local -a _scan_files=($glob_path)
|
||||||
|
shopt -u nullglob
|
||||||
|
if [[ "${#_scan_files[@]}" -gt 0 ]]; then
|
||||||
|
_ci_ssh_build_choices "${_scan_files[@]}"
|
||||||
|
if [[ "$CI_SSH_COUNT" -gt 0 ]]; then
|
||||||
|
local folder_selection
|
||||||
|
folder_selection=$(whiptail --backtitle "$backtitle" --title "SELECT FOLDER KEYS" \
|
||||||
|
--checklist "Select key(s) to import:" 20 140 10 "${CI_SSH_CHOICES[@]}" 3>&1 1>&2 2>&3) || return 1
|
||||||
|
for tag in $folder_selection; do
|
||||||
|
tag="${tag%\"}"
|
||||||
|
tag="${tag#\"}"
|
||||||
|
local line
|
||||||
|
line=$(grep -E "^${tag}\|" "$CI_SSH_MAPFILE" | head -n1 | cut -d'|' -f2-)
|
||||||
|
[[ -n "$line" ]] && printf '%s\n' "$line" >>"$CLOUDINIT_SSH_KEYS_TEMP"
|
||||||
|
done
|
||||||
|
local imported
|
||||||
|
imported=$(wc -l <"$CLOUDINIT_SSH_KEYS_TEMP")
|
||||||
|
echo -e "${ROOTSSH:- 🔑 }${BOLD}${DGN}SSH Keys: ${BGN}${imported} key(s) from folder${CL}"
|
||||||
|
else
|
||||||
|
whiptail --backtitle "$backtitle" --msgbox "No keys found in: $glob_path" 8 60
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
whiptail --backtitle "$backtitle" --msgbox "Path/glob returned no files." 8 60
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
none | *)
|
||||||
|
echo -e "${ROOTSSH:- 🔑 }${BOLD}${DGN}SSH Keys: ${BGN}none (password auth only)${CL}"
|
||||||
|
CLOUDINIT_SSH_KEYS=""
|
||||||
|
rm -f "$CLOUDINIT_SSH_KEYS_TEMP" "$CI_SSH_MAPFILE" 2>/dev/null
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Cleanup mapfile
|
||||||
|
rm -f "$CI_SSH_MAPFILE" 2>/dev/null
|
||||||
|
|
||||||
|
# Set the variable for setup_cloud_init to use
|
||||||
|
if [[ -s "$CLOUDINIT_SSH_KEYS_TEMP" ]]; then
|
||||||
|
CLOUDINIT_SSH_KEYS="$CLOUDINIT_SSH_KEYS_TEMP"
|
||||||
|
else
|
||||||
|
CLOUDINIT_SSH_KEYS=""
|
||||||
|
rm -f "$CLOUDINIT_SSH_KEYS_TEMP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# SECTION 3: HELPER FUNCTIONS
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@ -148,9 +341,10 @@ function setup_cloud_init() {
|
|||||||
local cipassword=$(openssl rand -base64 16)
|
local cipassword=$(openssl rand -base64 16)
|
||||||
qm set "$vmid" --cipassword "$cipassword" >/dev/null
|
qm set "$vmid" --cipassword "$cipassword" >/dev/null
|
||||||
|
|
||||||
# Add SSH keys if available
|
# Add SSH keys only if explicitly provided (not auto-imported from host)
|
||||||
if [ -f "$CLOUDINIT_SSH_KEYS" ]; then
|
if [ -n "${CLOUDINIT_SSH_KEYS:-}" ] && [ -f "$CLOUDINIT_SSH_KEYS" ]; then
|
||||||
qm set "$vmid" --sshkeys "$CLOUDINIT_SSH_KEYS" >/dev/null 2>&1 || true
|
qm set "$vmid" --sshkeys "$CLOUDINIT_SSH_KEYS" >/dev/null 2>&1 || true
|
||||||
|
_ci_msg_info "SSH keys imported from: $CLOUDINIT_SSH_KEYS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Configure network
|
# Configure network
|
||||||
|
|||||||
@ -169,6 +169,11 @@ function advanced_settings() {
|
|||||||
select_os
|
select_os
|
||||||
select_cloud_init
|
select_cloud_init
|
||||||
|
|
||||||
|
# SSH Key selection for Cloud-Init VMs
|
||||||
|
if [ "$USE_CLOUD_INIT" = "yes" ]; then
|
||||||
|
configure_cloudinit_ssh_keys || true
|
||||||
|
fi
|
||||||
|
|
||||||
METHOD="advanced"
|
METHOD="advanced"
|
||||||
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user